Den här historien handlar om ett administrativt kursplaneringssystem. I en offentlig verksamhet. Det utvecklades med stöd av konsulter, i en upphandling, enligt lagens alla regler. För 20 år sedan.
Inom vissa andra områden, såsom nätverk eller telekommunikation, förväntas ofta extrem stabilitet, upptid och leveransförmåga. Dessa attribut anses vara en självklarhet. Det blir glasklart om du tänker dig att din telefon eller ditt wifi bara fungerade 60% av tiden.
I administrativa stödsystem finns dock helt andra förväntningar.
Min kära mamma, som arbetade inom kommunal förvaltning och ekonomi, brukade säga: “Man får vara glad de dagar det fungerar”
Den här typen av förväntningar verkar påverka hur vi ser på IT-system. Du har förmodligen läst om förväntningar och utfall i medier. Senast i raden av haverier var journalsystemet Millenium. “Det är en katastrof”.
Eller vad sägs om “Huvudproblemet är att man glömde bort lärare och elever …” En talande kommentar från kritiken mot Stockholms Stads “Skolplattformen”. Som också stoltserar med ett katastrofalt införande, total brist på stabilitet och en kraftigt bristande funktionalitet.
KOPPS - Ett robust undantag
Kurs- och programplaneringssystemet, KOPPS, var ett system som jag personligen är stolt över att ha varit med att tagit fram. Då det begav sig för 20 år sedan. Nu 2025, ersätts funktionen med motsvarande i det nationella studiesystemet LADOK.
Jag var nyligen med på gravölen tillsammans med handläggare och ansvariga för KOPPS. Det fick mig att minnas utvecklingen och de principer vi följde.
KOPPS levererade underlag till bland annat antagning, kursinformation och scheman
Flera av kommentarerna från antagningshandläggarna under minnesstunden var i stil med:
“KOPPS var robust och stabilt, det fungerade alltid. Inte en enda gång var det stopp eller fel.”
Dessa ord gjorde mig berörd och glad, och det fick mig att reflektera över hur det kom sig att just robusthet och stabilitet var något som följde med KOPPS i så många år. Trots att både teknologin det byggde på och användargränssnittet skulle anses som ganska utdaterade idag. Vad gör ett system robust? Här listar jag några principer vi följde som jag tror hade stor betydelse.
KOPPS ingång - som det såg ut då - och nu
Robusthetsprincip 1: Inkludera robusthet i utvecklingsteamets mantra
Som man ropar får man svar
“Det måste fungera”, “Det måste vara pålitligt”, “Det får inte bli fel, det gäller våra studenter och antagning”
“Vi måste kunna lita på systemet till 100%, annars kommer inte KTH ha några studenter nästa termin.”
Så lät det när jag för 20 år sedan fick uppgiften att projektleda KOPPS-projektet. Det var inte bara en person som sa detta. ALLA ville samma sak. Förutom dessa önskemål och förhoppningar fick vi också andra tydliga direktiv.
“Gör vad ni vill, bara det blir förvaltningsbart!”, “Vi måste kunna ta hand om systemet, och vi har inte tid eller personal för att städa upp efter er.”
Det sades halvt med glimten i ögat, halvt med allra största allvar.
“Pålitligt” och “Förvaltningsbart” blev ett mantra för oss i teamet.
Vissa kanske kallar det mål, för oss var det ett mantra som sas till oss och som vi i teamet snart sa till andra, dagligen.
Robusthetsprincip 2: Fokusera på den mest kritiska funktionaliteten
Den mest robusta och stabila koden är den som inte skrivs!
Det är inget skämt, det är sant.
När vårt utvecklingsteam på ett par personer tog oss an projektet så möttes vi av en ganska enorm kravspec. Det var så man gjorde på den tiden, och tyvärr fortfarande idag på sina håll. Välskriven av en kunnig verksamhetsanalytiker, och väldigt omfattande. Alla önskvärda funktioner var täckta i den.
Det förväntade arbetssättet var att ta kravspecen, göra en tidsuppskattning och beta av en funktion i taget.
Jag och teamet insåg snabbt att det inte skulle fungera. Vi hade en skarp deadline som bara låg drygt en månad bort. Det nya systemet måste leverera underlag till den nationella antagningen (VHS) i tid annars skulle KTH inte kunna anta några studenter till kommande läsår. Åtminstone inte med mindre än att hela personalen hade fått jobba natt, helg och semestrar för att sköta det på papper och penna.
Istället dök vi mitt in i specen och tillsammans med kravställaren (verksamhetsexperten) identifierade vi vilken utdata som var absolut kritisk för att antagningen skulle kunna ske. Vi la den funktionen högst upp på vår todo-lista (som vi snart började kalla för backlog). Därefter stötte och blötte vi olika lösningsidéer för hur vi med kreativitet och tillfälliga handpåläggningar skulle kunna få en sådan funktion att komma i drift på bara en månad.
Det var en akutlösning som vi var tydliga med att den skulle kastas direkt efter första antagningen. Den får inte användas igen. Vi höll det löftet.
Den första lösningen var inte robust, men arbetssättet att identifiera den allra mest kritiska funktionen, utdatat till antagningen, visade sig vara robust. Samt modet att kasta det som byggts och som vi inte ville ha kvar.
Så fortsatte vi under hela utvecklingen. Identifiera det absolut viktigaste, skala av, skala ner och var mest stolt över den kod som inte skrivs.
Att prioritera utdatat visar sig också generellt vara en bra väg framåt för att undvika att utveckla saker som inte behövs, och alltså slippa onödig kod som behöver underhållas.
(Image by freepik)
Robusthetsprincip 3: Starta med förvaltningen
inkludera alltid personerna i utvecklingen som ska ta hand om systemet långsiktigt.
Vem ska drifta och förvalta systemet? Det var en fråga vi ställde oss från dag ett. Med hjälp av mantrat “förvaltningsbart, förvaltningsbart” från IT-förvaltningen.
Då, för 20 år sedan, var det ett ovanligt arbetssätt, att i princip börja projektet med att tänka på förvaltningen. Drift och överlämning var något som brukade göras i slutet av ett utvecklingsprojekt. Jag funderade då på hur man kan göra ett system förvaltningsbart. Ta med förvaltarna i utvecklingen, så klart!
Jag meddelade chefen på IT: “Om ni vill ha ett förvaltningsbart system, så måste ni förstås vara med och ta fram det. Så att det blir som ni vill! Att dokumentera era driftskrav räcker inte! Så vad gör vi för att få det att hända?”
Numera anses det mer självklart att utvecklings- och förvaltningsteamet är samma personer, det var det inte då.
Svaret jag fick från chefen var att han höll med, men att det inte fanns några i deras team som kunde avvaras. De var alltför upptagna med… förvaltning av andra system. Efter några samtal så kom vi överens om att till en början skulle minst en utvecklare från förvaltningen vara med på våra demos och planeringsmöten. För att få insyn och möjlighet till direkt feedback på tekniska och andra beslut vi tog. “Hur blir det här hållbart?” var en ständig fråga från dem som deltog i demos och planeringar.
Vi kom också överens med utvecklingschefen att de stegvis skulle börja fasa in en eller flera konsulter i förvaltningen av andra system, så att några utvecklare från IT-förvaltningen kunde bli en del av utvecklingsteamet för KOPPS.
Så skedde och efter något halvår så hade vi två engagerade utvecklare från dem i KOPPS- teamet.
Robusthetsprincip 4: Stå upp för den arkitektur du tror på
Ha modet att ta striden och den eventuella smällen
Fort skulle det gå, som i många utvecklingsprojekt. Vi var “försenade innan vi började” som många av oss inom systemutvecklingsprojekt varit med om.
Därför valde vi i utvecklingsteamet en teknisk “genväg” för att kunna driftsätta en del av systemet snabbt. Vi valde att göra en integration med CMS:et (Content Management System) som KTH använde för att publicera webbsidor. Det gjorde att vi inte behövde bygga ett användargränssnitt för redigering av kursinformation. Det var inte ett självklart beslut men vi valde att göra så både på grund av tidspress och möjligen en viss tro på att det skulle fungera.
Ja, vi sparade en del tid till en början.
Men…
Efter den första driftsättningen, då vi fick applåder för att vi levererade något så snart, som fungerade, så började vi snart se sprickor under ytan.
Den tekniska integrationen var knölig. När vi ändrade saker i kärnsystemet, blev det tidskrävande och svårt att testa uppdateringen i CMS:et. Vi märkte också att användarna fick en del problem. Koncepten hängde inte helt ihop mellan KOPPS och CMS:et. Vi var exempelvis tvungna att göra en del översättningar till CMS:ets terminologi som inte var helt klockrena.
Det här känner nog många användare igen som arbetat i en lärplattform, schemaläggning eller annat administrativt system där koncepten inte är logiska. Sådant kan ofta bero på en integration med något system som är “nära men inte riktigt”.
Det här var en mycket jobbig punkt i projektet. Vi måste backa. Vi måste i princip ta det nya systemet ur drift ett tag för att göra om till den plan vi hade från början. Att bygga användargränssnittet själva.
Jag gick med mössan i hand till IT-chefen och verksamhetschefen. Samtidigt med huvudet högt för jag visste att det här var enda hållbara vägen framåt.
“Vi behöver ungefär 6 veckor till för att göra om, göra rätt. Det vi har nu kommer att gå sönder. Det ser ut att fungera nu, men det är inte robust. Om jag förstått det rätt så vill ni ha pålitlighet och förvaltningsbarhet. Det är på väg att bli motsatsen om vi fortsätter”
Svaret jag fick från en av dem:
“Du vet att man brukar hänga projektledare för sådant här va?” med en viss glimt i ögat.
Hur allvarligt var det menat?
Jag kunde inte annat än att säga “Ja, om du tror att det är lösningen på problemet, varsågod.”
Jag hade också hela utvecklingsteamet bakom mig, vi hade haft en djupdykning i problemet vid några tillfällen. Jag var inte ensam, vi var överens.
Efter ett par ganska tuffa möten, så bestämde vi tillsammans med ledningen och beställare att gå på vår linje. Vi backar och gör en mer hållbar arkitektur.
(Image by freepik)
Robusthetsprincip 5: Tänk test först
Testdrivet på alla nivåer - även behov och krav - och automatisera dem
KOPPS-projektet startades i den tidiga eran av utveckklingsfilosofin eXtreme Programming (XP) och testdriven utveckling. Vårt team bestämde oss tidigt för att ha ett ambitiöst förhållningssätt till automatiska test.
Koden som skrevs skulle inledas med att skriva ett test eller flera. Testen utvecklades före en bit kod istället för efteråt. Sedan skrevs kod som gjorde att ett test passerade, vilket gjorde att automatiska test kördes direkt när en liten funktion var i drift. Det skapar en robusthet.
Vi införde också ett “acceptanstest-drivet” arbetssätt. Vilket innebär att innan en funktion skulle utvecklas så definierades ett eller flera acceptanstest tillsammans med domänexperten (som också hade rollen produktägare). Hur skulle verksamheten, användarna, testa funktionen? Vad förväntades exakt för resultat när funktionen fanns på plats?
Vi använde det tidiga ramverket FIT (Framework for Integration Test) som gjorde att acceptanstesten som definierades också kunde köras automatiskt mot koden.
Det arbetssättet tvingade oss att kommunicera mycket specifikt med våra närmaste intressenter. Genom det arbetssättet tvingades vi och de att definiera och förstå vad som verkligen var viktigt och att definiera begrepp och förväntningar. En infrastruktur byggdes upp som körde acceptans-testen automatiskt vid varje nytt systembygge.
Det fanns flera utmaningar med arbetssättet. Ibland upplevdes det som overhead-arbete, och onödigt tidskrävande att leverera en liten funktion, men steg för steg märktes att systemet blev… robust. Mycket få, om ens några, buggar eller konstiga systemfel uppstod, både då under den tiden, och nu 20 år senare.
Huruvida automattest användes flitigt efter vi lämnat vet jag inte, men att designa systemet utifrån ett test-först-tänk, även på acceptansnivå, skapade uppenbarligen något som fungerade långsiktigt.
Robusthetsprincip 6: Fler ögon på samma funktion
Parprogrammering - daglig kunskapsspridning och insyn gör systemet mer robust och bättre designat.
Teamet beslöt tidigt att i princip parprogrammera allt. Parprogrammering innebär att vara två personer vid ett tangentbord, enligt ett roterande schema.
Att få till rutinerna för att passa alla var inte enkelt. Det kan vara ganska utmattande och ibland verkar det onödigt att sitta två och jobba tillsammans framför en skärm hela dagar. Med tiden hittade teamet sin form, men varför vi gjorde det var tydligt för alla. “Genom att vi jobbar med samma kod minst två personer, så finns alltid två personer som kan koden. Två personer som har delat sin uppfattning och styrt designbeslut och tolkningar.”
Vi roterade så att alla jobbade med alla delar av koden. Trots att vissa var specialister på t.ex databaser, användargränssnitt eller annat. Specialisten fick skina och dela med sig när den hade sitt område framför sig, och fick insyn i och lära sig hur andra områden fungerade när den parade i något område som var mindre känt. Samt bidra med sin särskilda syn och kunskap om behov i andra delar av systemet.
Att rotera vid tangentbordet ger tid till kunskapsspridning, reflektion och insyn
Robusthetsprincip 7: Inkludera användarna tidigt
Vad har användares engagemang med robusthet att göra? Ja, vad har det inte?
Det kan tyckas självklart, men det var inte det då i systemutvecklingsprojekt, och tyvärr är det fortfarande alltför ovanligt idag. Särskilt i offentlig verksamhet verkar det som när man läser nyheterna.
Vi i utvecklingsteamet var oerhört tacksamma för att vi fick (eller snarare tog :-) ) med oss en domänexpert i det dagliga utvecklingsarbetet. Han som tagit fram kravspecen satt tillsammans med oss och jobbade. Till en början med andra uppgifter eftersom han var “klar” med specen, men med tiden mer och mer engagerad i det dagliga utvecklingsarbetet.
Det var förstås en stor tillgång och utöver det bestämde vi oss tidigt för att så ofta som möjligt stämma av med de som skulle använda KOPPS, handläggarna. Det gjorde vi genom studiebesök hos dem, genom att bjuda in dem till demos med feedback-stunder och ibland även planeringar. Eller, det var inget beslut, för oss var det självklart. Hur skulle vi annars göra något som fungerade?
Med tiden lyckades vi även få acceptans för och styra ekonomiska prioriteringar för att ta in hjälp av en UX-designer på deltid i teamet. Då höjdes nivån på användar-inkluderingen. Hon drev både arbetssätt och test för att öka insyn och feedback.
Genom att handläggarna blev alltmer aktiva i leveranser, test och tidig feedback så upptäckte vi felantaganden som kunde utredas tidigt, och konstiga fel i datat eller gränssnittet kunde hanteras innan de blivit för svåra att ta itu med.
En del svåra designbeslut och bortprioriteringar kunde förankras snabbt med användarna vilket ledde till att det gick att undvika en hel del onödig komplexitet. Onödigt komplexa system blir svårare att testa, förvalta och mindre robusta.
Två av utvecklarna som var med från start (Joakim Holm & Fredrik Tarberg) samt Caroline Boivie Ekstrand, chef för verksamhetsuppföljning (VOS-gruppen) på KTH
Ett robust system
Arbetssätten och tankesätten ovan var en stor orsak till att KOPPS, 20 år senare, får en så fin avslutning. Ett system som förtjänade en egen gravöl och minnesstund. Ett systemutvecklingsprojekt som lärde mig, och kanske fler, en hel del om hur ett stabilt och i princip buggfritt administrativt stödsystem kan byggas upp.
Olika system och projekt har olika mål och prioriteringar. I KOPPS var pålitlighet och robusthet ett mantra. Så blev det.
För närvarande jobbar jag i ett utvecklingsprojekt som också har robusthet i fokus. Utifrån en lite annan vinkel och med vissa andra prioriteringar. Delar av systemet behöver vara extremt robust rent driftsmässigt. Andra delar behöver vara extremt robust i fråga om integritetskänslig data och därför designas datahanteringen på ett annorlunda vis än normalt. Andra delar behöver inte alls vara robust, de är utforskande och experimentella och inget som ska förvaltas särskilt länge.
Du kanske jobbar med en tjänst som har helt andra mål än just robusthet. Det skulle kunna vara snabbhet, användarglädje, försäljning, säkerhet, kostnadseffektivitet eller något annat.
Frågan är om det går att uppfylla något av det utan åtminstone ett visst mått av robusthet?