Hur uppstår legacykod?

Hur uppstår legacykod? Och vad kan vi göra för att undvika den? Andreas Brink, konsult på Consignit, berättar mer.

Vad är legacykod?
Begreppet legacy används på olika sätt. Rent ordagrant betyder det ju arv, vilket skulle kunna tolkas som det vi redan har, all befintlig kod alltså. Men ofta används ordet för att beskriva system som verksamheten är beroende av, men som är svåra, eller till och med omöjliga att förändra - något problematiskt med andra ord. 

Vi talar om gamla system alltså?
Många menar nog det implicit när de använder ordet legacy - gamla system på omoderna plattformar som är svåra att underhålla. Ett nyare användningssätt av legacykod - som jag gillar bättre - är kod som är svår att ändra.

Varför tycker du att det är en bättre definition?
Det avspeglar att det är koden som är problemet, inte systemets ålder. Sättet man uttrycker sig på påverkar sättet man analyserar och angriper problemet på. Branschen har problem med legacykod och har lärt sig att acceptera ofantliga underhållskostnader. Alternativet är att skriva om systemet från början, vilket ofta leder till att historien upprepar sig igen. Inget av dessa två scenarion är bra, och jag anser inte vi bör hamna där så ofta som vi gör. Att tala om kod som legacy oavsett om den är gammal eller inte är ett viktigt första steg för att förstå varför vi får problem längre fram i ett systems livscykel.

Vad är problemet - varför får vi legacysystem?
Det är inte ett problem, och legacykod är heller inte ett binärt tillstånd - det är egenskaper som uppkommer gradvis. Kostnaden för att underhålla ett system är en funktion av de interna mjukvarukvaliteterna. Ett mindre akademiskt uttryckssätt skulle kunna vara systemets kod- eller designkvalitet. Denna är relativt lätt att observera, i alla fall i viss utsträckning. Man kan se problem väldigt tidigt i ett systems livscykel, men ofta görs det inget åt det.

Menar du att vi börjar programmera innan vi har fått en bra design?  Skall vi lägga mer tid på att hitta rätt design från början?
Nej, min erfarenhet är att det snarare är det synsättet som är en del av problemet. Det jag menar är att vi ofta fokuserar mer på att göra rätt än att reagera på det som inte är bra. Vi vill så gärna ha en enkel metod eller riktlinje som säger hur, eller hur mycket, vi skall designa, och resten skall bara vara enkel kodning. Men så fungerar det inte. Design handlar om att göra en ansats, utvärdera resultatet och sedan anpassa sig. Detta måste göras kontinuerligt under ett systems livslängd. 

Hur tycker du att vi bör ta oss an design för att undvika legacykod?
Som jag redan har nämnt måste vi lära oss utvärdera design. Det talas så mycket om verktyg och metoder idag, inte minst inom agile, ett område jag verkligen gillar. Men det går varken att använda eller utvärdera metoder om man inte vet vad som är ett bra slutresultat. När koden är dålig måste man reagera. Alltför ofta hanteras koden som en sekundär artefakt; den bör istället sättas i fokus.

Är inte det ett typiskt teknikerperspektiv som leder till suboptimering - att koden är så viktig? Analysen, att förstå systemets syfte, är väl viktigare?
Jag säger absolut inte emot dig vad gäller att förstå syftet: Hellre rätt system med dålig design än fel system med bra design. Men bra analys och bra design är inte två kvaliteter som tävlar om ett begränsat utrymme. Man behöver inte tumma på det ena för att det andra håller hög kvalitet, och de bästa utvecklarna förstår båda perspektiven. Det jag menar är att legacyproblematiken har att göra med dålig kod, inte att systemet gör fel sak. Ifall systemet hade gjort fel sak hade inte verksamheten använt det. Dålig kod gör det svårt att anpassa systemet efter verksamhetens förändrade behov, och ofta förstår vi inte de verkliga behoven förrän systemet har varit i drift ett tag. Bra design är essentiellt för att kunna skapa långsiktigt värde med hjälp av mjukvara, eftersom den behöver förändras.

Jag förstår det där med bra design, men varför är koden så viktig?
För mig är kod och design i mångt och mycket samma sak. Först och främst är det koden som skall underhållas, inte en designmodell, inte primärt i alla fall - designen sitter i koden. Om koden är svår att förstå och ändra har man problem. Det kan vara problem på låg nivå, eller problem med arkitekturen. Många problem är faktiskt ganska lätta att observera i kod även om man inte vet vad systemet håller på med. Man kanske inte ser de grundläggande orsakerna, men man ser symptom som man känner igen.

Kan du ge exempel?
Långa metoder och stora klasser är typiska exempel, och duplicerad kod. Man kan också se om den som skrivit koden behärskar programmeringsspråkets möjligheter att lösa problem på det enklaste möjliga sättet. En variant på samma tema är avsaknaden av objektorienterade mekanismer för att förenkla en lösning. Väldigt ofta blir lösningarna krångliga helt i onödan.

Systemet kan vara svårt att förstå för att detaljerna i koden är otydliga, eller för att detaljerna gör att det är svårt att se de stora dragen - brus som gör det svårt att uppfatta det väsentliga i arkitektur eller affärsregler. Ofta kan man göra väldigt stora förbättringar med ganska små medel. Det handlar om att skriva koden så att den kommunicerar väl med läsaren. Det finns två viktiga historier att berätta: Dels de bakomliggande affärsreglerna och användningsfallen, dels de tekniska strategierna som används för att implementera lösningen. Bra kod separerar dessa två perspektiv så att man kan läsa koden på olika nivåer.

Rent konkret handlar det om tekniskt triviala saker som namngivning och nedbrytning och strukturering av uttryck och metoder. Jag har en känsla av att en satsning på hög kvalitet på den här nivån är mycket kostnadseffektivt. Det är nämligen relativt lätt att lära sig att göra detta bättre, och extrakostnaden för ett bättre utförande är oftast marginell. När man väl har lärt sig hur man skall göra vill säga; men det är som sagt relativt enkla tekniker.

Hur lär man sig att skriva bra kod?
Man tränar. Men då behöver man en målbild. Det kräver att man läser kod och pratar om design. I många organisationer lyser dessa diskussioner med sin frånvaro. Vid kodgranskningar är det vanligt att man uppehåller sig kring indenteringar, och namnsättningsstandarder och diskuterar alldeles för lite design, ofta undviker man det helt. Flertalet utvecklare skulle kunna höja kvaliteten på koden de skriver med relativt enkla medel. Många skulle tycka det var utvecklande och kul; många andra skulle i alla fall anstränga sig för att göra ett bra jobb.

I en grupp med mindre erfarna utvecklare behövs minst en utvecklare med stark designkompetens som kan driva kvalitetsarbetet på kodnivå. Kodgranskningar och parprogrammering är två sätt att utbyta erfarenheter om design. Det finns en hel del bra litteratur på området. Framförallt gillar jag Martin Fowlers Refactoring-bok. Fowler diskuterar vad som är dålig kod - han kallar det smells - och har en katalog av konkreta tekniker, så kallade refactorings, som beskriver hur man förändrar koden så att den blir bättre.

Du fokuserar mycket på koden. Hur skall vi göra för få en bra arkitektur?
Arkitektur och kod är inte två väsensskilda saker. Arkitekturen avspeglas i koden, men allt i koden är inte arkitektur. Och arkitektur är svårt, det är verkligen ett stort ämne. Jag tror mycket på arkitektrollens betydelse för ett bra resultat. Arkitekten skall vara med och skriva kod, det är en förutsättning för ett lyckat resultat.

För att återgå till koden: Om arkitekturen har förbättringspotential kommer detta att synas i koden. En enkel beskrivning av att designa är att skapa struktur. Arkitektur kan ses som de viktiga strukturerna i ett visst perspektiv av systemet - det kan finnas många perspektiv. Ett enkelt program som Hello World har en väldigt enkel struktur, kanske en klass med en enda metod; det är tillräckligt mycket struktur för att hantera komplexiteten i den applikationen. I en mer komplex applikation behöver man skapa mer struktur i lösningen. Ett tydligt tecken på att det finns behov av mer struktur är när man observerar duplicerad kod. Att fokusera på att ta bort duplicerad kod kommer per automatik att driva fram struktur, inte en given struktur, men i alla fall någon struktur. En erfaren designer har olika lösningsalternativ att välja mellan, var och ett med sina för och nackdelar. Det finns inte ett rätt sätt att bygga ett system.  

Ok, inga enkla svar här inte?
Det är riktigt, det finns ingen enskild enkel lösning på hur man åstadkommer bra design. Men det finns en väldigt stor verktygslåda med många små tekniker och mönster som vart och ett kan göra skillnad. Man behöver inte kunna vartenda verktyg utantill för att vara en bra designer, men man måste känna till att ett verktyg existerar och förstå på ett ungefär vad det kan hjälpa till med, annars kommer man aldrig att veta när man skall plocka fram och pröva det. Och det är bara genom att pröva som man kan lära sig hur det verkligen fungerar; böcker är bara en introduktion. Design är ingenting man lär sig över en natt.

Kan du avslutningsvis nämna två vanliga misstag som resulterar i legacykod, samt åtgärder för att förhindra det.
Jag vet inte vilka misstag som är vanligast, och jag vill inte gradera dem heller, men det här är i alla fall två misstag av lite olika karaktär. Ett vanligt misstag är att man sätter ribban för lågt vad gäller kodkvalitet. Jag tror att man ofta inte sätter ribban alls faktiskt, det får bli som det blir. Man kan ha en helt ok arkitektur, i alla fall i stora delar, men delar av systemet kan vara i princip omöjliga att förstå på grund av dålig kod på lägre nivå. Och brister och lämpliga lösningar på arkitekturell nivå kan bli i princip omöjliga att identifiera på grund av allt brus. En duktig programmerare jobbar inte snabbare med hjälp av låg kodkvalitet; han jobbar snabbare med hjälp av smart design - två flugor i en smäll. Kräv bra kod och hjälp utvecklare att lära sig hur man skriver den. Anställ utvecklare som vet hur man gör och låt dem visa vägen. 

Ett annat misstag som görs är att man separerar utveckling och förvaltning i två separata delar och organisationer. Risken är mycket stor att förvaltningsprojektet saknar den förståelse - både inom problemdomänen och inom mjukvarudesignen - som behövs för att bibehålla eller förbättra kvaliteten och vidareutveckla arkitekturen på ett vettigt sätt. Man tappar kontinuiteten helt enkelt. Att över huvud taget se på mjukvarusystem som något som tillverkas och sen bara skall underhållas är ett grundproblem - man får vad man ber om lite grann. Vilken kreativ utvecklare vill jobba med ett system som är färdigdesignat och bara skall underhållas?

Egentligen tror jag man har ett väldigt bra utgångsläge att göra något riktigt bra av ett system i samband med att det har gått över i "förvaltning". Mycket av det stora krav- och analysarbetet är utfört. Man får verklighetsbaserad feedback på vad som fungerar och vad som inte fungerar, och det blir ofta lättare att prioritera arbetsinsatser när man ser hur systemet verkligen används. Om vi kan göra förvaltningsarbetet mer attraktivt har vi en chans att behålla nyckelpersonerna som kan driva fram bra arkitektur och hög kvalitet kontinuerligt under ett systems livslängd. Den så kallade utvecklingsfasen är bara en start; potentialen för förbättring av arkitektur och utvecklingsprocessen är ofta stor. Utnyttja det och skapa en win-win situation: Intressantare arbete för duktiga utvecklare och ett mer anpassningsbart system med högre kvalitet som genererar större värde till verksamheten.  

 

 

Senaste besökta utbildningar