Buggar som duggar tätt, sinkade leveranser på grund av nyckelpersoner som blivit sjuka, mängder med hår som slits när det visar sig att en installation baserats på en gammal dokumentversion. Låter det överdrivet? Faktum är att detta är vardagsmat i många projekt.
Andreas Eriksson, Java Technical Lead på Cybercom Group East, är förespråkare av effektiv systemutveckling. Han reder ut begreppen och kommer med några råd på vägen för att undvika de vanligaste problemen.
Vad innebär effektiv systemutveckling?
- Enligt min uppfattning innebär det att man arbetar utifrån några relativt enkla principer för att skapa bra implementation och hög kvalitet i mjukvaran, samt levande och korrekt dokumentation. Och icke att förglömma - motiverade projektdeltagare. Jag ljuger om jag säger att det bara är tre principer/tekniker man ska använda. Men för att göra det hela lite överskådligt ska vi lyfta fram begreppen Continuous Integration (CI), Test-driven Development (TDD) samt samägd kod och dokumentation. Till dessa principer vill jag addera en stor dos sunt förnuft och ett agilt arbetssätt.
Continuous Integration
Kontinuerlig integration handlar om att automatisera byggprocesser och exekvera tester för att säkerställa att integrationen av ny kod har lyckats. Det innebär att man har en central byggserver (Continuous Integration Server) som kör igång byggprocesser vid en definierad händelse, t ex när en utvecklare checkar in ny kod i versionshanterings-systemet. Tanken är att fånga upp problemen i tidigt skede, innan de hinner orsaka någon stor skada. Automatisering av byggprocessen ger mer tid till utveckling. Kontinuerlig integration bör göras manuellt (när man sitter och utvecklar), vid definierad händelse (till exempel när någon checkar in ny kod) och schemalagt (till exempel varje lördag natt).
Test-driven Development
Testdriven utveckling är en metod för att utveckla mjukvara. Den går ut på att man skriver tester (oftast enhetstester) för för-ändringar eller nya funktioner, innan själva implementationen görs. Kod som ska ut i produktion måste passera de skrivna testerna.
Uppstår nya förhållanden, till exempel ny funktionalitet eller omskriven kod, tillämpas så kallad refaktorering för att anpassa sig till det nya förhållandet. Refaktorering är en disciplin för att i små steg omstrukturera den interna strukturen till det bättre, utan att förändra dess externa beteende.
Hur strikt tillämpar du testdriven utveckling?
- Det gäller att ta hänsyn till behovsbilden men också att använda sitt sunda förnuft. Jag tycker till exempel att det funkar att skriva tester efter att implementationen blivit gjord, så länge man klarar av att vara kritisk mot sin egen kod. Ett bra sätt att utveckla tester är att be en kollega att ge ‘implementation vad den tål'. Det finns också verktyg som kan användas för att mäta testtäckning. Det ger en bild över hur mycket av din kod som faktiskt testas.
Samägd dokumentation och kod
Jag anser att alla deltagare i ett projekt har gemensam skyldighet att se till att dokumentation om mjukvaran är korrekt och uppdaterad. Samma sak gäller mjukvarans källkod. Kalle bör kunna hjälpa till att skriva dokumentation om hur en viss funktion i mjukvaran fungerar, trots att Lisa implementerat funktionen. Uppstår det en bugg som Kalle har skapat, ska Lisa kunna fixa den, lika gärna som Kalle.
Det blir svårt att skylla ifrån sig med andra ord?
- Ja, så skulle man också kunna uttrycka sig. Men det är inte det som är det huvudsakliga syftet. Kollektivt ansvar ger ett bra
kunskapsutbyte utvecklarna emellan. I och med detta minimeras risken att projektet hakar upp sig på nyckelpersoner. De flesta har nog någon gång suttit med i projekt där leveransen dragit ut på tiden för att någon blivit sjuk. Det menar jag är ineffektiv systemutveckling.
Om att följa principerna till punkt och pricka
Det kollektiva ansvaret för koden går ju att övervaka och kontrollera automatiskt. Vi kan t ex få reda på om testerna täcker tillräckligt mycket av den skrivna koden och om kodnings-konventioner efterlevs. Det går även att få mätetal om komplexitet och så vidare.
Att principen för samägd dokumentation efterlevs är dock svårare att hålla koll på. I det ideala projektet behövs ingen övervakare som smäller utvecklarna på fingrarna - det är ju trots allt ett kollektivt ansvar som gäller. Det är dock inte helt ovanligt att det faktiskt finns en person i projektet som ansvarar för principernas efterlevnad.
Jag hoppas att alla projektdeltagare som förstår fördelarna med effektiv systemutveckling, tillåts skola in de mindre erfarna utvecklarna. Då kan man eliminera många fallgropar.
Vilka käppar i hjulet finns vid effektiv systemutveckling?
- Det finns alltid fallgropar och misstag i ett projekt, oavsett vilka principer man jobbar efter. Slarv och glömska är en farlig bov som kan leda till att utvecklarna inte checkar in kod kontinuerligt. Testerna och koden integreras då inte tillräckligt ofta och det blir svårt att upptäcka felaktigheter i koden. Likgiltighet inför det kollektiva ansvaret för mjukvaran och att inte hjälpa till med dokumentationen är några andra allvarliga faktorer. Bristfälligt engagemang hos en person kan leda till att flera deltagare i projektet blir lidande. Ivrighet och stress kan också ge projektet en törn. Vissa utvecklare vill inget hellre än att ett bygge ska gå igenom. Man kommenterar bort tester som fallerar istället för att åtgärda källkoden så att testerna lyckas. Längre fram i tiden stöter man ju på ännu större felaktigheter men det tänker inte alla på. En vanlig fallgrop rör återkopplingen från de kontinuerliga byggena. Ibland är feedbacken för knapphändig. Ibland är det precis tvärtom - utvecklarna upplever att de drunknar i status-information från byggen. Detta undviks om projektgruppen från början kommer överens om vilken nivå som ska gälla.
Fördelar med effektiv systemutveckling
Kostnaden för buggar brukar i regel öka i takt med tiden mellan att felaktigheten uppstår och att denna upptäcks. Den snabba feedback som testdriven utveckling ger, minskar ju tidsåtgången. Därmed sjunker kostnaderna för buggrättningar och integrations-problematik. I och med den kontinuerliga integrationen, säkerställs att den kod som implementeras faktiskt är i linje med den rest-erande mjukvaran. Koden verifieras inte bara med dina egna tester utan även med andras. Eftersom byggprocessen är automatiserad kan utvecklarna ägna mer tid till att faktiskt utveckla. Byggprocessen skulle till och med kunna utföra en leverans till testare och andra intressenter, vilket eliminerar ytterligare tidskrävande aktiviteter från utvecklaren. Alla tester finns kvar som kvalitetssäkring för framtida vidareutvecklingar, dokumentationen hålls levande via t ex en wiki som flera projekt-deltagare under tiden kan bidra till och fler personer kan dela på kunskapen om mjukvaran.
Vad bör man tänka på om man vill införa effektiv systemutveckling?
- Se till att använda versionshantering av artefakter (kod, doku-mentation). Tillämpa en testdriven approach. Skapa byggscript för alla monotona aktiviteter som inte bidrar till att koden utökas, t ex kompilering, exekvering av tester, skapande av rapporter och leverans. Automatisera med hjälp av kontinuerlig integration. Använd en kommunikationskanal (e-post, RSS, wiki, SMS eller liknande) för informationsspridning om byggen, tester och så vidare.
Några avslutande tips och råd?
- Inför inte allt på en gång. Ta små steg anpassat till den aktuella behovsbilden. Glöm framför allt inte att ha kul och att du tillämpar
effektiv systemutveckling för att skapa mjukvara som du kan vara stolt över.
Författare: Andreas Eriksson / Java Technical Lead /Cybercom Group East / lärare på Informator
Blogg: http://www.iamandreas.blogspot.com/