Här tar jag upp
Agile betyder vig, lättrörlig.
Det är ett samlingsnamn för olika utvecklingsmodeller som försöker att undvika problemen med vattenfallsmodellen.
Här försöker man producera kod som är körbar "hela tiden".
Två viktiga tekniker som används i de olika utvecklingsmodellerna är refactoring och unit testing.
Jag kommer att beskriva Extreme programming som är (tycker jag) den mest utpräglade av de agila metoderna.
Ibland räknas även iterative design till (ID) denna grupp, men vanligtvis räknas inte ID hit.
Den mest kända modellen i denna grupp är väl Scrum. Precis som ID bygger Scrum på iterationer av fix längd.
Med refactoring menas att förändra ett program för att göra det lättare att förstå eller lättare att modifiera. Förändringarna i programmet ska inte ändra vad programmet gör.
I refactoring angriper man vanligtvis kod som har olika brister. För att ta några konkreta exempel:
Det kan också handla om mera subtila brister:
(Kommentarer är OK men är koden svår att förstå är det bättre att städa upp den än att kommentera den.)
Det är vanligt att använda refactoring för att göra det lättare att genomföra planerade ändringar.
När man väl bestämt sig för att ett program inte är bra brukar det vara uppenbart vad som bör göras för att städa upp det. Man kan tex
Om vi till exempel har en metod med en lång och krånglig parameterlista är det lämpligt att fråga:
Man kan till exempel flytta metoden från en klass till en annan (så att parametrarna inte behöver skickas) eller flytta instansvariabler (av samma skäl).
Man kan tänka sig många typer av tester:
och även olika tillfällen när det passar att testa koden:
Om man gör testning till en del av utvecklingsprocessen är det lämpligt att automatisera testerna. Här har man en svit av tester som kan köras automatiskt.
En god princip: om du hittar en bug som inte fångas av något befintligt test, skapa (och lägg till) ett test till testsviten som fångar buggen. Efter att du lagt till testet kan du fixa buggen och kolla (med hjälp av testet) att buggen är fixad. Om du kör testsviten under projektets gång kan du vara säker på att buggen fångas om den skulle återuppstå.
En typ av testning som lämpar sig bra för automatisering och testning under utveckling är unit testing. Här testar man enskilda komponenter.
Idén är att testa testa enstaka klasser och metoder.
Det finns verktyg som hjälper till, tex JUnit. Användning av JUnit.
Unit testing är särskilt värdefullt för komponenter som är komplexa och svåra att testa när de integrerats i applikationen.
Innan vi tittar på extreme programming (XP) vill jag skissa på en enkel utvecklingsmodell som passar bra att använda i små projekt.
Vi vill ha snabb återkoppling på följande frågor
En lösning:
Det finns en risk att programmet efterhand blir mer rörigt och svårarbetat. Lösningen på det problemet är (förstås) refactoring.
Det finns en risk att refactoring råkar införa buggar. Lösningen är förstås unit testing eller någon annan metod för automatisk testning.
Man kan kanske se XP som en vidareutveckling av den här informella modellen, anpassad för lite större grupper och lite större projekt.
Den modell för agil systemutveckling som jag tar upp kallas extreme programming (beskrivs i boken Extreme programming explained av Kent Beck). Som man kan gissa representerar den en ganska extrem syn på programutveckling.
Extreme programming (XP) kan ses som en reaktion på den traditionella utvecklingsmetodikerna (till exempel vattenfall), och ett försök att uppnå samma mål med andra medel.
Man brukar sammanfatta XP i 12 regler (practises). Jag listar dem här.
Beslut om hur nästa steg ska se ut måste förstås ta hänsyn till affärsmässiga aspekter, men de tekniska apekterna är också viktiga: Kan vi ta fram den nya versionen på rimlig tid? Leder den oss mot projektets mål?
Viktigt är förstås vem som bestämmer hur nästa steg ska se ut. Beck tänker sig att projektet ska ledas av de som arbetar med systemet.
En enkel övergripande bild av hur systemet ska fungera. Här kan man både ta upp hur systemet ska organiseras internt och hur det ska se ut för användaren. Alla som medverkar i projektet ska vara medvetna om denna.
Skriv det enklaste programmet som klarar alla tester:
I många sammanhang tas det för givet att man bör koda för framtiden; man ska försöka förutse framtida behov och ta hänsyn till det i programmet. XP säger motsatsen: Koda inte för framtiden.
Det finns en poäng här. Även om man anar ett framtida behov är det vanskligt att ta hänsyn till det i förväg. Vi har ännu inte analyserat problemställningen och vi har inget bra sätt att testa om de åtgärder vi tar till verkligen kommer att hjälpa oss i framtiden.
Min egen erfarenhet är att det är svårt att koda för framtiden. När det förutsedda framtida behovet blir verklighet är den lösning man fick fram ofta inte riktigt den lösning som visar sig behövas. Man blir tvungen att göra om i alla fall.
Skriv en svit av tester för att testa systemet i stort och dess enskilda delar. Vanligtvis använder man olika former av unit testing.
Skriv tester som beskriver önskat beteende hos klasserna och metoderna innan du börjar koda!
Testerna blir specifikationen.
Använd något verktyg som hjälper dig att köra alla testerna.
Om du vid provkörning stöter på en bugg i systemet, skriv först ett unit test som fångar buggen innan du åtgärdar den.
Försök ständigt förenkla programmet!
Ett exempel: Två klasser som gör ungefär samma sak—ersätt dem med en enda klass.
Det här är ofta krångligt: Klasserna kan ha olika metodnamn och se olika ut. Vi kan bli tvungna att ändra kod som använder klasserna (trots att det inte är nåt fel på koden).
Annat exempel: Två klasser har delvis samma funktionalitet.
En lösning kan vara att skapa en abstrakt klass som båda ärver från. Placera den gemensamma funktionaliteten i den abstrakta klassen. En annan lösning kan vara att flytta ut funktionalitet från klasserna och placera den nån annanstans.
All kod skrivs i grupper av två, där man delar en dator, med ett tangentbord och en mus. Den som inte använder tangentbordet följer arbetet och har ansvaret för överblickande frågor: Passar lösningen in i systemet? Finns det testfall som ännu inte fungerar? Kan vi förenkla lösningen?
Ett problem med parprogrammering är att man i ett slag har skurit ner arbetsstyrkan till hälften. Å andra sidan bör en grupp av två göra färre fel. Som du vet tar felsökning ofta en stor del av utvecklingstiden.
Alla har ansvar för all kod.
Alla har rätt att ändra.
Om en programmerare ser en brist i din kod (eller en möjlighet att förbättra) är det hans eller hennes skyldighet att göra detta.
Den vanliga lösningen är ju annars att olika utvecklare har ansvar för olika delar av systemet. En nackdel är att problem ibland tar lång tid att lösa om en person har mycket att göra eller prioriterar fel. Detta kan påverka andras arbete.
Å andra sidan kan en utvecklare med bristande omdöme ställa till med stora problem om han ändrar på många ställen i systemet. Andra regler hjälper här: Parprogrammering reducerar risken för enkla slarvfel och andra missar. Automatiska tester reducerar risken att att man inte upptäcker att ens ändringar leder till oväntade fel.
Nyskriven kod ska testas i systemet efter (högst) några timmar.
Varje par har ansvar för att föra in sin förändring och se till att den klarar testsviten till 100%.
Om de inte klarar det—släng ändringarna.
Kent Beck säger inget om detta, men jag antar att tanken är att ett system för versionshantering används. Ett versionshanteringssystem gör det möjligt att checka ut en egen version av ett projekt, göra ändringar, och sedan checka in ändringarna i systemet. Jag brukar undvika att uttrycka mig kategoriskt, men i alla projekt med mer än en utvecklare bör man absolut använda någon form av versionshantering.
Inte nödvändigt att säga mycket om detta. Om man är trött gör man fler fel och blir mindre produktiv.
Ha en "äkta kund" (dvs en person som kommer att använda det färdiga systemet) på plats. Kunden ska hjälpa programmerarna att bedöma vad som är viktigt och provköra systemet.
I många projekt med mer än en inblandad blir det ibland konflikter av ganska larviga skäl.
Exempel: Ska man skriva
void f() { ... }eller
void f() { ... }???
Om flera personer ska arbeta med samma kod måste man enas om en standard. Det spelar ingen större roll vilket alternativ man väljer (jag föredrar det första) men alla måste vara klara över vad som gäller.
Traditionell systemutveckling lägger stor vikt på planering.
Extreme programming fokuserar på programmet...
Ytligt sett kan XP och ID se ganska olika ut: ID passar in på det stora företaget där projekten är toppstyrda och ofta stora (hundratals utvecklare eller fler). XP är mer anpassat för mindre projekt där alla känner alla och där varje utvecklare kan påverka.
Trots det representerar XP och ID i grunden en likartad syn på program och programutveckling:
För skojs skull skrev jag ner några frågor som kan vara värda att grunna på. Flera av frågorna saknar enkla svar.