Puke: Hantera din designskuld
- fre 6 feb, 2009 kl 11:37
- 27 kommentarer
- Puke
Rubriken för första Puke-inlägget var ”Men fulhacka då!”. Jag tänkte att jag skulle utveckla resonemanget lite om fulhack.
Det första man ska vara medveten om är att ett fulhack är vad Ward Cunningham m. fl. kallar för en ”designskuld” (se ”Technical Debt”, ”Design Debt” mm.). En friktion i utvecklingsorganisationen är den om desigskulder/fulhack. Ett av skälen till att utvecklare skyr fulhack (även då hacken är ekonomiskt motiverade) är att de har dåliga erfarenheter av att bli dubbelbestraffade för dem.
Scenariot är ofta detta: I slutet på en releasecykel vill produktägaren pressa in funktionalitet som är viktig för kunden, men som inte är trivial att införa sådan som kodbasen ser ut nu. Den önskade funktionaliteten har ingen lösning som harmonierar mer arkitekturen.
Utvecklarna måste då antingen försvara sin kodbas, vilket gör produktägaren harmsen (och ofta på goda grunder: funktionen kan vara avgörande för kunden, och kunden kan vara avgörande för företaget); eller ge efter i form av en lösning som på ett eller annat sätt förstör kodbasen, arkitekturellt sett.
En degenererad kodbas är trögare att arbeta med (måste påminna om Emelies ”clean code” här), varför utvecklarnas produktivitet sjunker, vilket produktägaren bestraffar utvecklarna för. Alltså: först tvinga utvecklarna att knyta samman sina skosnören, och sedan skälla på dem när de inte springer lika fort som tidigare.
Det är ju uppenbart så att produktägaren i dessa fall inte tar ansvar för sina beslut och sin produkt. Inget i processen tvingar den heller att ta ansvar: likt en bortskämd unge kan produktägaren ena stunden önska och kräva, och sedan gnälla över konsekvenserna. Allt medan produkten degenererar.
Lösningen är att hantera denna designskuld på samma sätt som man hanterar andra skulder: man synliggör dem, betalar kostnaden för dem, och ser dem som möjliggörare som dock har ett pris i form av en kalkylerad risk.
När man tänker på det är det inte så underligt. Hela produkten är faktiskt redan resultatet av ett sådant risktagande, en sådan lånerisk. Kostnaderna för utvecklingen av en produkt tas ju innan produkten börjar generera intäkter. Verksamheten är alltså redan inställd på den typen av överväganden.
Felet som utvecklarna gör är att de inte synliggör designskulden när den uppstår. Verksamheten har inga problem att hantera lånerisker, men de måste först och främst veta att de har dem.
Hur synliggör man då designskulder? Det enkla sättet är att se dem som tidsskulder. I klarhet: när man inför fulhacket gör man samtidigt ett estimat för vad det kostar att göra förändringen ogjord och kanske vad det kostar att göra det bra. Detta läggs som ett ärende i ärendehanteringssystemet (produktens backlog). Samtidigt markerar man i koden med ”Kludge” i en kommentar, och kanske ett namn eller annan identifikation så att det blir en länk mellan ärendehantering och kodbas.
Nu är fulhacket med på agendan. I och med att man lägger den i produktens backlog blir den ett ansvar för produktägaren att inför varje cykel ta ställning till och prioritera upp eller ner. Hur skulden i praktiken sedan kommer att hanteras beror helt på hur produktägaren vill göra. Men ägaren kommer aldrig mer att kunna ignorera eller låta bli att hantera den.
Eller skylla den på någon annan än sig själv.
Väl talat, broder.
Synd bara att tidsuppskattningar som gäller teknisk skuld har samma egenskaper som ”vanliga” tidsuppskattningar: De blir på sin höjd aningen bättre än kvalificerade gissningar, de har ett kort bäst-före datum och de beror oftast på många oförutsägbara faktorer.
Men som du skriver så tror jag ändå att det är väldigt bra att ”få med fulhacket på agendan”. Att det blir synligt är kanske 80% av grejen. (Och tidsuppkattningens precision 20%)
Instämmer till helt och fullo med att lösningen är att synliggöra.
Bekymret kommer ett tag senare (tänk 2-3år) då räntan på den tekniska skulden blivit så hög att ägaren inte längre har råd att betala. Hur gör Puke då?
Enda gången ett fulhack är OK i mina ögon är när man gör det så löst kopplat att man klippa av banden med en träsax.
”Hur gör Puke då?”
Byter jobb. Om ägaren har haft en synlig designskuld i sin backlog i tre år utan att göra något åt den, förtjänar ägaren all olycka.
Poängen är att någon äger frågan att balansera teknik och affär. Ibland är god teknik en dålig affär och tvärtom. Då måste någon balansera intressekonflikten.
Det är inte utvecklarna som äger den frågan, om de inte också samtidigt tar det fulla affärsmässiga ansvaret och gör koden säljbar.
Vilket jag inte är motståndare till, men det är en annan fråga.
Angående tidsuppskattningar: det stämmer! Och är ett problem. Men i brist på tidsuppskattning: bara antalet införda skulder är en signal.
Och i slutändan är det produktägaren som bestämmer prioriteringen. Produktägaren är en nyckelfigur i sammanhanget och är ytterst ansvarig för produkten.
”Produktägaren är en nyckelfigur i sammanhanget och är ytterst ansvarig för produkten.”
Absolut, vad jag är ute efter är att den insikten saknas hos många produktägare.
Jag antar denna koppling mellan att låna och återbetala går igen inom andra områden.
Vissa människor förstår inte att det man lånar måste betalas av någon gång, och då oftast lite dyrare (ränta). De konsumerar bara och hamnar så småningom hos Kronofogden eller i en del fall hos TV3’s ”Lysfällan”.
Det är klart att en mjukvara alltid har en viss skuld, som i den bästa av världar kontinuerligt betalas av genom refaktorering osv. Vad det kokar ner till är nog mest sunt förnuft och ansvarstagande från både produktägare och utvecklare.
Det finns två problem med teknisk skuld:
1. Den repareras aldrig eftersom det hela tiden finns ”viktigare” saker att göra som har med verksamheten att göra. Det är svårt att förklara för en produktägare hur viktigt det är att ta bort den där klassen med 5000 rader kod när användrna vill ha ett nytt imatningsfält.
2. The broken window theory http://www.codinghorror.com/blog/archives/000326.html
I stället för att fulhacka så kan man säga till scrum-mastern eller pruduktägaren att man behöver mer tid för att bli färdig och så får man oftast det.
Därmed inte sagt att man alltid skall sträva efter dom mest tekniskt eleganta lösningarna men jag tycker personligen att man kan skriva kod snabbt men ändå skriva kod som är lättläslig och lättunderhållbar.
Men det är klart att det blir fulhack i vissa extrema fall och det skapar ju arbetstillfällen, så den som förlorar mest på fulhacken är företaget som äger mjukvaran som tyvärr saknar förståelse för att prioritera betalningen av teknisk skuld. Det är ofta så att man får smyga in skuldbetalningar samtidigt som man utvecklar en ny feature. Det är tragiskt att det är så men det beror nog på att dom som är på en högre nivå saknar utvecklarbakgrund och på så sätt saknar förståelse för konsekvenserna av en för stor teknisk skuld.
”Den repareras aldrig”
Jo. Om produktägaren vill.
”dom som är på en högre nivå saknar utvecklarbakgrund”
Ja, alltså… i produktägarrollen behövs en generalist. Med gott grip på både affärer och teknik.
> “Den repareras aldrig”
> Jo. Om produktägaren vill.
Men det är ofta där det spricker. Produktägaren kanske delvis förstår problemet men det svårt att räkna om teknisk skuld i pengar och därför svårt att jämföra med features.
> “dom som är på en högre nivå saknar utvecklarbakgrund”
> Ja, alltså… i produktägarrollen behövs en generalist. Med gott grip på både affärer och teknik.
Absolut men vart hittar man en sån ;-)
Känns som om vi är överäns om att det är produktägarens ansvar så fort som problemen lyfts upp i backloggen. I praktiken funkar det ju inte så bra tyvärr så det bästa man kan göra tror jag är att göra allt för att minimera den tekniska skulden även om det känns surt att ingen tackar en för det men man kan iaf veta att man har gjort ett bra jobb som man kan va stolt över.
Det som jag tycker är intressant är att det mesta med processer och problem inom utveckling lyfts fram av oss utvecklare bara för att vi har i oss av naturen att lösa problem. Det hade varit kul om det fanns en global organsiation av produktägare/management som utbytte idér om hur man kan blir bättre på sina yrken.
”Men det är ofta där det spricker. Produktägaren kanske delvis förstår ”
Helt rätt. Finessen med en metod som Scrum är att det blir produktägarens uttalade ansvar. Inte utvecklarens outtalade ansvar. Och med kass produktägare kommer katastrofer.
Vilket leder mig in på min nästa käpphäst: att produktägare behöver produktägarutbildning. Vilket är en helt ny serie blogginlägg.
Men det är inte Pukes problem.
”det bästa man kan göra tror jag är att göra allt för att minimera den tekniska skulden ”
NEJ! Det är det som är grejen.
Teknisk skuld, precis som all annan skuld, kan vara ekonomiskt fördelaktig. Då ska den naturligtvis tas. Allt annat vore tjänstefel av dem som har att ansvara för ekonomin.
Vad du föreslår är att minimera den tekniska skulden endast för att du vill skydda produktägare från information eller situationer de inte kan hantera rätt.
Men att dalta med omgivningen löser inte problemen. Att i stillhet kompensera för andras brister hjälper vare sig dig eller dem. Det är produktägarens ansvar att göra dessa avvägningar.
Därför: synliggör teknisk skuld. Misslyckas produktägaren med att hantera den så skjuter den ut sig själv.
Eller, vilket är något jag gärna gör: tag produktägarrollen.
@Ola: Hur skall man utbilda produktägare så att de kan väga teknisk skuld? Går det att förvandla teknisk skuld till något beräkningbart. ”Uppskatta i poäng och lägg på produktbackloggen”. Uppskattningen är missvisande efter viss tid (kanske redan från början) och den visar heller inte hur kostsamt det kan bli i senare delar av produktens livstid, såsom vid underhåll, felsökning och vidareutveckling. Så länge vi har mänskliga utvecklare (som skall tolka affärskrav och föreställningar om prestanda osv till kod) så kommer vi också ofta få ta beslut pga att vi gör tolkningar av vad någon skrivit (i oförståelse eller ofullständighet).
En idé slog mig när jag läste ditt inlägg, Fredrik; Kanske vore det effektfullt att lägga in en automatisk backlog-prioriteringsfaktor som är beroende av tidsuppskattningens ålder? Alltså så som det görs i vissa ärendehanteringssystem. Ju längre tiden går, desto högre prio-poäng får ärendet. Detta reflekterar ju verkligheten eftersom fulhackets ”tekniska skuldränta” ökar hela tiden.
Sen handlar det bara om att kalibrera fram rätt viktning…
Som jag föreslog i inlägget: bokför den tekniska skulden i form av en backlog-punkt där du tidsestimerar hur lång tid det tar att få fulhacket ogjort (alternativt hur lång tid det tar att införa en bättre lösning).
Gärna under en egen ärendekategori (”technical debt” eller ”ugly hack” eller så).
Då har du ett kvantifierat mått på hur kodbasen degenererar.
Men vilket kvantifierbart sätt som helst är bra. Vinsten ligger i synliggörandet. I och med synliggörandet görs det till produktägarens problem, och produktägaren får då själv fundera över vilken sorts vidareutbildning som krävs.
Den andra delen av frågan rör vilken sorts utbildning produktägare (och resten av organisationen) behöver i största allmänhet. Där säger jag: arkitektur. Ingen utanför utvecklarnas krets behöver kunna koda. Men alla måste ha en bild av systemets centrala komponenter och deras respektive ansvarsområde, och ett ungefärligt hum om hur dessa komponenter samarbetar.
Precis som utvecklarna behöver ett hum om hur säljprocess fungerar, och alla behöver grundkunskaper i företagsekonomi.
Jag pratar om kunskaper motsvarande en halv universitetstermin, typ introduktionskursen. Inget dramatiskt med andra ord, utan ett översiktligt införande i den grundläggande terminologin.
Jag håller med om att man bör bokföra teknisk skuld och man bör ju minska den men det är väldigt svårt att väga en teknisk skuld mot en feature även om man är erfaren utvecklare.
Jag är ändå inne på den linjen att man skall försöka göra allt för att förhindra att det upstår. Det är ju ofta man själv som står för tidsestimeringen och visar det sig att den inte håller och man har frågat efter mer tid men blivit nekad då får man ju ta en teknisk skuld och dokumentera det men jag tycker att man bör undvika det så långt som det är möjligt.
”det är väldigt svårt att väga en teknisk skuld mot en feature även om man är erfaren utvecklare.”
Du ska inte väga en teknisk skuld mot en feature, om du är utvecklare.
Det är produktägaren som ska göra den avvägningen. Det är nämligen en affärsmässig avvägning, eftersom featuren potentiellt sett innebär en intäkt och skulden innebär en kostnad.
”man skall försöka göra allt för att förhindra att det upstår.”
I så fall fattar du egenmäktigt beslutet att organisationen ska undvika att ta vissa affärsrisker.
”Det är produktägaren som ska göra den avvägningen. Det är nämligen en affärsmässig avvägning, eftersom featuren potentiellt sett innebär en intäkt och skulden innebär en kostnad.”
Frågan är vem som skall kunna avgöra hur stor kostnaden är av en teknisk skuld. En teknisk skuld är ju ofta av den typen som potentiellt kan bli ett problem för att det leder till ostabilitet eller att det försämrar koden som gör att man ”kanske” måste skriva om vissa delar eller hela systemet på lång sikt. Det går inte att räkna om något sådant i pengar. Det är svårt till omöjligt att beräkna den totala kostnaden av en teknisk skuld.
Det jag däremot tycker har funkat bra som jag varit med om är att ha en slot av utvevklingstiden varje sprint till att jobba med teknisk skuldavskrivning och på så sätt så behöver man inte prioritera feature mot en teknisk skuld med andra ord så jämför man mer äpplen med äpplen.
”I så fall fattar du egenmäktigt beslutet att organisationen ska undvika att ta vissa affärsrisker.”
Att fatta egenmäktiga beslut är något vi utvecklare måste göra hela tiden. Vem bad tex mig att använda EJB2 eller Spring. Vi har rätt stort anvsvar över den totala kostnaden för ett system beroende på vad vi som utvecklare väljer för lösningar. Så jag ser inga konstigheter i detta.
Det viktiga är att man hela tiden jobbar för produkten och företagets bästa. Det är inte alltid lätt att avgöra vad det är men vi utvecklare har ett stort ansvar där eftersom vi är dom enda som förstår mjukvaran på företaget.
”Frågan är vem som skall kunna avgöra hur stor kostnaden är av en teknisk skuld. En teknisk skuld är ju ofta av den typen som potentiellt kan bli ett problem”
Det stämmer. Kostnaden för en teknisk skuld är en spekulation. Man gissar och tar en chansning, eftersom man vet att man inte kan kontrollera alla variabler.
Men detsamma gäller ju intäktsmöjligheten. Den är också en potential. Man kan göra sitt bästa för att öka chansen till god intäkt, men i slutändan är även det en spekulation.
All affärsverksamhet är från början en spekulation i risker och chanser. Det är därför jag argumenterar för att beslutet att ta en teknisk skuld i slutändan ligger hos den som har ett affärsansvar för produkten.
”Att fatta egenmäktiga beslut är något vi utvecklare måste göra hela tiden. ”
Om vi ser att våra beslut har affärsmässiga implikationer måste vi kommunicera dessa.
Det låter som om du beskriver en ignorant beställare. Acceptera inte det.
Oj, här går det hett till.
Problemet som jag ser det är att de (utvecklarna) som skapar teknisk skuld med beställarnas goda minne är att det sällan samma personer som är där när det är dags (måste) betalas tillbaka för att systemet inte ska braka samman och fortfarande kunna vidareutvecklas.
Kostnaden för tekniska skulden ökar oftast ju längre man väntar.
Ibland kan man avskriva skulden genom att man klarar sig tills det är dags att lägga ner av andra skäl.
Ibland så måste en totalomskrivning göra med mindre teknisk skuld och kan göras parallellt medan det gamla lever.
Håller fullständigt med om att av ekonomiska skäl finns anledning att skapa denna skuld för att huvudtaget komma upp på banan.
Finns otal historier om system som man försökt göra ”perfekta” från början som har lagts ner innan de ens levererats pga att kostnaderna skenat.
Även om produktägare blivit informerade och accepterat att skulden måste regleras inom tid så glömmer de ofta bort det tills det är dags.
Men om man bara har en beställare som betalar så kanske man hoppar när denne säger till när alternativen tryter.
Att en sån här diskussion kan bli livlig beror också kanske på att man har olika syn på vad som innefattas av fulhack och teknisk skuld. Det kan ju variera rätt mycket i storleksgrad och omfattning från allt från fulkod till dåliga designval.
Det jag tycker lyfts fram bra med Puke är att man skall tänka efter ordentligt om ett visst pattern verkligen gör systemet bättre och om det är värt det rent ekonomiskt.
*If in doubt leave it out* funkar bra att följa när det kommer till designval. Det är väldigt lätt att man försöker stödja hela allt i universum och helt plötsligt blir det för komplext för att användas.
@Martin: Ah – bra vidareutveckling (från att bara lägga till ”statiskt” på backloggen).
@Per: Instämmer till 100 % i ”Puke [lyfter fram] att man skall tänka efter ordentligt om ett visst pattern verkligen [är] värt det rent ekonomiskt”.
@Ola: Du har lyft upp ett bra ämne som vi alla tampas med dagligen. Att göra teknisk skuld synlig för produktägaren måste bli lika självklart som att använda SCM. Att få produktägaren att kunna väga teknisk skuld vs ”annat” är målet och ett drömscenario – eller finns sådan beställarorganisation i närheten?
@Fredrik: Den beställarkompetensen måste uppstå. Om inte annat på darwinistiskt sätt: organisationer utan den kompetensen får komparativa nackdelar när konkurrenterna tar språnget.
När den här problematiken tacklas från affärssidan heter det inte ”Puke”, utan ”Business Alignment”, ett område som har problemställningen ”Hur få IT att gå i takt med resten av organisationen”?
Puke är en del av mitt svar på den frågan.
Vad säger Puke om Test First och JUnit?
Alltid lättare att införa (och motivera) en teknisk skuld än vara den som får betala skulden.
Har erfarenhet av båda sidor.
Men som Per skriver så om det är tveksamt att något behövs så behövs det nog inte, åtminstone inte nu och inom en snar framtid.
Utveckla inte för långt in i framtiden då när framtiden är här så är den inte vad man trodde den skulle bli då (hängde ni med? nästan inte ens jag själv gör det).
@Mika:
TestFirst+JUnit:
Å ena sidan: Puke kräver agilitet, och agilitet kräver refaktorering. Refaktorering kräver testbarhet. Ju större testbarhet, desto billigare och bättre refaktorering. TestFirst och JUnit (och CI-motorer och allt), ger större testbarhet.
Å andra sidan: TestFirst ger en spec som är direkt testbar. Du vet direkt om koden följer specen eller ej. Men det ger ingenting i fråga om att säkerställa att man kommit fram till RÄTT SPEC! Själva utvecklingens grundfråga: VAD ska vi koda? står kvar.