Systemutveckling

Vad gör mig till en bra systemutvecklare och arkitekt?

Jag har arbetat med systemutveckling i olika roller under hela mitt yrkesverksamma liv, varav 15 år som utvecklare och arkitekt, men också flera år som chef, coach, och teamledare, och sett många olika projekt och förvaltningsorganisationer från många olika perspektiv. Jag är van att jobba djupt, över hela stacken, och behärskar frontend, backend, och datalagring och kommunikation, men har ofta på senare år arbetat mer med backendprogrammering och datalagring än frontend.  

Jag har aldrig varit någon stark anhängare av teorin att erfarenhet av ett specifikt programspråk, middleware eller annat tekniskt val är avgörande för om man kan arbeta effektivt i ett team, utan att generella kunskaper inom systemutveckling, god kännedom om tekniska praktika som TDD och kodstandarder, och att vara en bra lagspelare är betydligt viktigare. Med det sagt har jag i första hand arbetat med Microsoftteknik; C#, MS SQL Server, IIS, Azure, Azure Stack, Windows Server, Active Directory, etc., samt webbtekniker som Javascript, CSS, och HTML, men har också lång erfarenhet av C++. Utöver det har jag arbetat professionellt med TypeScript, Angular, x86 och 68000-assembler, C, PHP, VB .Net, ASP, Visual Basic, VBA, PowerShell, MySql, och PostgreSQL. Utöver detta har jag också bedrivit hobbyprojekt i Java, Lisp, Clojure, Pascal, Delphi, och Basic. Jag har också erfarenhet av en lång, lång rad av tekniska verktyg, allt från Visual Studio till Git och WordPress, som jag inte tänker lista här.

Precis som i mitt arbete med agila metoder och ledarskap arbetar jag evidensdrivet i mitt utvecklingsarbete. Det innebär att jag väljer arkitektur och design utifrån beprövade mönster som är anpassade till uppgiften, men också att jag tillämpar praktiska tekniker som t.ex. testdriven utveckling som har bevisad effekt. Software Craftsmanship är ett samlingsbegrepp för dessa tekniker, som tyvärr ofta har prioriterats bort när man väljer i metod- och verktygsfloran. Dock är dessa metoder viktiga för att producera system med hög kvalitet som är lätta att underhålla och förändra. “Räntan” på den tekniska skulden, dvs hur mycket extra tid det tar att genomföra en förändring, är 100% i ett genomsnittligt system. I klartext tar det alltså dubbelt så många mantimmar att förändra de flesta system som det skulle kunna ta, eftersom de har utvecklats på mindre effektiva sätt.

Software Craftsmanship

Allt eftersom agile i många utövares ögon – i synnerhet de som kom från en mer teknisk bakgrund – vattnades ur och fokuserade allt mer på processer och metoder och allt mindre på tekniska praktika växte en ny rörelse fram, den så kallade Software Craftsmanship Movement. Här ville man flytta tillbaka fokus på de praktiska aspekterna av mjukvaruutvecklingen. Under konferensen Agile 2008 föreslog Robert C. Martin en femte värdering till det agila manifestets ursprungliga fyra – hantverksskicklighet över skit. I december samma år hölls en konferens i Chicago, där ett nytt manifest togs fram som skulle lyfta fram dessa värderingar:

I vår strävan efter att bli skickliga mjukvaruhantverkare höjer vi ribban för professionell mjukvaruutveckling genom att praktisera och hjälpa andra att lära sig hantverket. Genom detta arbete har vi kommit att värdesätta:

Inte bara fungerande mjukvara, men också välskriven mjukvara

Inte bara anpassning till förändring, men också att kontinuerligt tillföra värde

Inte bara individer och interaktioner, men också ett samfund av yrkesmän

Inte bara kundsamarbete, men också produktiva partnerskap

Det vill säga, i vår strävan efter punkterna till vänster finner vi punkterna till höger oumbärliga

Dessa praktiska aspekter består naturligtvis till viss del av tekniska verktyg som krävs för att understödja agila mål som kontinuerliga leveranser, exempelvis automatisering av byggen och releaser, men också till stor del av handgripliga tekniker utvecklare använder i sitt dagliga arbete. Nedan följer ett kort urval.

Testdriven utveckling

Testdriven utveckling (TDD) är en utveckling av Test First Developement, en av grundpelarna i Extreme Programming. TDD är inte bara ett sätt att bygga enhetstester till sin kod utan bör också leda till en enklare och mer optimerad design, en bättre användning av refaktorering och därmed högre kodkvalitet, samt ett korrekt modulariserat system. 

Testdriven utveckling utgår från en kort process:

  • Skriv ett testfall för den funktionalitet som ska implementeras, och kör testet (Red)
  • Skriv koden som implementerar den enklaste möjliga lösningen för att testet ska gå igenom (Green)
  • Refaktorisera
  • Om koden nu är så generell att den kan hantera alla tänkbara varianter av indata så är koden klar, annars gå tillbaka till Red.

En vanlig missuppfattning om TDD är att syftet är att öka den funktionella kvaliteten, dvs att undvika buggar. TDD har i och för sig den effekten (TDD minskar antalet buggar med ca 50%), men huvudsyftet är att producera kod som är lättare att läsa, förstå, och underhålla. Enhetstesterna driver dels designen när de skrivs innan koden, dvs interfacet definieras från testet och därmed från konsumentperspektivet, och inte från implementationen, och dels gör de det ofarligt att ändra i koden så att den blir bättre. TDD är den effektivaste metoden för att undvika och minska teknisk skuld.

Gör det då någon skillnad om enhetstester skrivs först, som i TDD, eller efter att koden har skrivits? Jämför man test-first med test-last har kod som har skrivits test-first dubbelt så hög täckningsgrad, nästan hälften så många kodrader per metod, färre metoder per klass, mindre cyklomatisk komplexitet, och lägre stackdjup. Tyvärr är det ändå många som skriver sina tester efter att de skrivit sin kod – om de alls använder sig av enhetstester – i tron att det inte spelar någon roll.

Kodstandarder och Clean Code

Det mest kända och använda verket om kodstandarder idag är förmodligen Robert C. Martin’s Clean Code, som har fått stort genomslag. Vissa av rekommendationerna i Clean Code är okontroversiella (även om de tyvärr inte alltid följs), t.ex. att ge klasser, funktioner, och variabler bra namn, vissa är allmänt accepterade idag, men såg annorlunda ut för 20-25 år sedan, t.ex. synen på polymorfism, och vissa är – trots verkets stora genomslag – fortfarande kontroversiella eller okända. Ett bra exempel är synen på kommentarer.

När jag har intervjuat studenter och mer erfarna utvecklare som har sökt arbete eller projektarbete, frågar jag ofta på vilket sätt de säkerställer att den kod de skriver är lätt att läsa och förstå, och kan förvaltas av andra. Ett mycket vanligt svar är att de kommenterar flitigt. Martin rekommenderar, med ett fåtal undantag, att undvika att kommentera kod, av flera skäl, varav några av viktigaste är att kommentarer ofta är missvisande eftersom de inte uppdateras när koden förändras, att många kommentarer inte tillför något, och att kommentarer är ett missat tillfälle att istället refaktorisera och skriva mer lättläst kod. Det Martin säger är inget nytt. Förutom Martin är troligen de viktigaste verken på området Elements of Programming Style (Kernighan & Plauger, 1974) och Code Complete (McConnell, 1993). 

…the only reliable documentation of a computer program is the code itself.

Elements of Programming Style

Good code is its own best documentation. As you’re about to add a comment, ask yourself, ’How can I improve the code so that this comment isn’t needed?’

Code Complete

Det Martin skriver är alltså inget nytt, men har han rätt? Ja, forskning visar att kommentarer ofta är felaktiga, och ca 80% tillför inget till läsarens förståelse av koden, och totalt beskriver nästan 99% av alla kommentarer sådant som antingen redan tydligt framgår av koden eller som med fördel kan tas bort och ersättas av tydligare kod. Andel kommentarsrader korrelerar också positivt med antal defekter – ju fler kommentarer en kodmassa har, desto fler buggar har den.

Kommentarer är bara ett exempel, men ett som belyser problemet. Vi vet vad som utgör en bra kodstandard, men trots det gör man i många team tvärt om. En bra kodstandard är den näst effektivaste metoden för att undvika teknisk skuld, efter testdriven utveckling.

Parprogrammering

Parprogrammering är en metod där två utvecklare tillsammans delar en dator för att utveckla en funktion eller en del av en funktion. Det huvudsakliga syftet med parprogrammering är att höja kvaliteten på koden och minska antalet defekter, men de flesta upplever också en högre trivsel.

Kod producerad med hjälp av parprogrammering har en bättre design, och är upp till 40% kortare än individuellt producerad kod. Den tar ca 15% längre tid (i mantimmar) att producera , men avkastningen på den investeringen är ca 1.600%, i första hand beroende på en ökad kodkvalitet och färre defekter (8% till 50%, variationen i olika studier är tyvärr stor)..

Parprogrammering är något många ägnar sig åt, men vad gör de egentligen? I många fall är det två personer som sitter tillsammans och arbetar, utan någon större struktur. Gott så, men är det verkligen vad parprogrammering är, och gör det effektivt?

En av utvecklarna skriver koden, och kallas föraren. Den andra, som observerar, diskuterar, kommer med idéer och påpekar eventuella problem, kallas navigatör. Föraren och navigatören byter roll med jämna mellanrum. Föraren och navigatören arbetar tillsammans för att skriva koden, och har inte uppdelade roller mellan sig, förutom att sköta tangentbordet. Navigatören och föraren måste byta roll ofta, och navigatören måste vara engagerad i arbetet för att parprogrammering ska ha positiva effekter – dvs om samma person kodar hela tiden finns ingen mätbar effekt av parprogrammering. 

I de mest produktiva paren frågar deltagarna varandra ofta om varandras uppfattning, förklarar för varandra hur de tänker, kritiserar varandras förslag och sammanfattar var de står, ofta genom att navigatören har en liten checklista de båda går igenom med jämna mellanrum – dvs parprogrammering är mest effektivt om det sker på ett strukturerat sätt med en tydlig metod.

Olika personer reagerar på olika typer av fel, och kan tillsammans upptäcka fler fel än en enskild person, men över tid konvergerar två utvecklares känslighet och effekten avtar. Det är därför viktigt att byta partner med jämna mellanrum, och att alla utvecklare arbetar med alla andra över tid, så kallad promiskuös parprogrammering. Studier visar att man uppnår maximal effekt om man byter par ungefär varannan timme, förutsatt att teamet är väl fungerande – de flesta som tillämpar parprogrammering byter partner alldeles för sällan.

Certifieringar, kurser, och utbildningar

  • Universitetsutbildning i datavetenskap
  • Professional Scrum Developer
  • Testdriven Utveckling med Alistair Cockburn

Vill du veta mer?

Kontakta mig gärna! Jag tar uppdrag som systemutvecklare och arkitekt, men utbildar och coachar också i Software Craftsmanship.