Visar inlägg med etikett micro services. Visa alla inlägg
Visar inlägg med etikett micro services. Visa alla inlägg

fredag 12 februari 2016

En agil mjukvaruarkitektur

En agil mjukvaruutveckling brukar beskrivas som att man låter programvaran växa genom evolution i stället för genom en förutbestämd plan. Man hävdar alltså (korrekt) att det är svårt att i förväg förstå vilka konsekvenser beslut om en applikation får, förrän man faktiskt upplever hur det fungerar i "verkligheten", alltså när det är implementerat och klart.

Så, om du är agil så ska du göra fel, ändra, se att det fortfarande inte är bra och ändra igen. När du är klar med detta så ska du välkomna förändrade krav. Men i de projekt jag har jobbat i har man ansett att en utforskande ansats är för dyr, eftersom det är svårt att förändra när saker väl blivit skrivna. När kraven förändras väljer man ta långa omvägar för att det är så svårt att ändra i det man redan har. Med andra ord väljer man bort ett agilt förhållningssätt och lägger stor möda på att försöka att göra rätt på första försöket.

Jag ska nedan försöka beskriva några mönster och dess möjlighet till att göra det lättare att arbeta agilt. Dessa mönster kommer inte gratis på något sätt. Man kan se det lite som att med dessa mönster hoppas man på en komplexitetsökning som ser ut som O(log n) där den traditionella modellen något elakt skulle efterlikna O(n*n) (n i kvadrat alltså). Dock så börjar den agila modellen med en mycket större insats i kunskap och stödjande tjänster för att inte leda till katastrofens rand. Vet du inte vad du gör är det läge att låta bli och inte härma de som faktiskt vet vad de gör och varför.

Microservices
Med microservices väljer man att dela upp sin applikation i många små fristående delar i stället för en. Varje microservice blir simpel men man blir inte av med komplexiteten, utan den flyttar ut i nätverket där man hoppas att den ska gå och hantera på ett bättre sätt. Microservices stödjer det agila arbetssättet genom att du kan byta ut en microservices relativt enkelt utan att påverka resten av systemet och du är fri att ta beslut om hur din microservices ska fungera internt utan hänsyn till hur de andra är implementerade, kanske byta till ett mer lämpat programmeringsspråk, uppgradera bibliotek etc etc.

Prestanda brukar vara den brukar beskrivas som  drivkraften för microservices, men jag skulle hävda att möjligheten till att olika utvecklingsteam kan arbeta utan att påverka varandra är mycket starkare i normalfallet (Amazon och Netflix är inte normalfall)

Eventsourcing
Med eventsourcing sparar du ditt data utifrån vilka förändringar som har gjorts i systemet (verben) i stället för att lagra entiteter (substantiven). Man kan jämföra med en läkare som har sparat din journal (med alla undersökningar, prover och anteckningar) och använder den som grund för att ställa diagnos och väljer att inte ordinera jordnötter eftersom det står att du är allergisk i journalen till motsats till en akutläkare som ser att blodet sprutar och får utgå från det hen kan se just nu.

Med eventsourcing har du inte en modell utan snarare en modell per händelse och en modell per slutsats eller rapport du önskar skapa från dina händelser, även om du naturligtvis kan ha en övergripande modell någonstans i bakgrunden. Flera modeller gör det svårare att hitta hur ett enskilt attribut kom till världen men som å andra sidan gör att du kan anpassa dina modeller efter olika behov i stället för att anpassa behovet efter modellen. Attribut som tex rubrikfärg har jag sett många gånger krypa in i tex en person-entitet eller telefonnummer-entitet där man kanske hade varit mer betjänt av att ha en modell över presentations-stöd och en annan över domän-information. Så i stället för att ha en modell där en förändring påverkar all annan funktionalitet väljer man att kunna förändra en funktions modell separat från de andra. Notera att detta kan innebära en hel del dubbellagring av data och synkronisering av detta data måste ske på ett kontrollerat sätt.

Immutable
Att vara immutable innebär att man aldrig modifierar sitt data, man lägger bara till ny information till systemet. Det kanske låter som lite slöseri med hårddisk men det ger en del intressanta möjligheter, främst att du får möjlighet att titta på hur ditt data såg ut vid en tidigare tidpunkt. Som extra bonus blir cachning enkelt, eftersom den information som finns där aldrig förändras (det kommer ny information naturligtvis, men de gamla värdena är orörda).

Man kan dra immutable-begreppet längre än data och ta in begreppet immutable-everywhere. I princip innebär det att du aldrig ändrar i integrationer, du skapar en ny och den gamla får leva vidare tills det är säkert att ta bort den. Du ändrar aldrig i dina installationer på dina servrar utan gör en ny och låter den gamla leva vidare tills det är säkert att ta bort den gamla. Det ger bland annat möjlighet att skapa en ny integration till en ny klient som innehåller alla de senaste funktionerna, samtidigt som övriga klienter kan fortsätta att använda den gamla tjänsten tills de är redo att uppgradera. Drar man den tanken till sin spets får varje klient sin egen tjänst och kan där med förändras oberoende av andras behov.

Även vid serverdrift, särskilt i mer eller mindre virtuella sammanhang kan man välja att skapa en ny "image" som kan driftsättas parallellt med den gamla installationen och testas om den fungerar i produktion på en delmängd av trafiken innan man "pekar om" alla användare till den nya servern.

Automatisering
Människan är ganska dålig på att utföra repetitiva uppgifter och detta leder till ett kontrollbehov, eftersom vi kort och gott inte är att lita på. Detta leder till ett behov av kontrollstrukturer som i sig själva driver behovet av fler människor som ska utföra alla kontroller och i sin tur kontrolleras och ingen tillför värde för användaren av systemet (åtminstone inte direkt).

Vägen ut ur detta är automatisering. Efter att ha kontrollerat att automaterna(?) fungerar (tex gör rätt sak vid feltillstånd) kan de släppas lösa. Eftersom du kan ha ett större förtroende för att saker och ting fungerar kommer du också våga att förändra och förbättra i dina system. Detta leder till att ditt system blir större efter som fler uppgifter behöver programmeras och underhållas.

Sammanfattning
Att vara agil är så mycket mer än att ha en iterativ process. Det handlar också om att inte bara vara en döv, stum och blind idiot för vad kraven på systemet säger idag utan även för vad de kan komma att säga i morgon och förutsätta att saker kommer att förändras. Att placerat sig i en position där man kan välkomna förändringar även sent i projektet.

De mönster jag skrivit om ovan kommer inte gratis utan är dyra, både i tid och kunskap. De löser vissa problem men för med sig många andra som du också måste förstå innan du börjar, oavsett projektstorlek. Men när du börjar få problem med att du inte längre kan anpassa ditt system snabbt och smidigt kommer du önska att du tittat på ovanstående mycket tidigare.

torsdag 4 februari 2016

En ny skön värld

Ibland får man uppenbarelser, en känsla av att man förstått något och nu vet hur en aspekt av världen fungerar och varför det är som det är. Allt är självklart och nu är det dags att agera och inte svamla något om kanske och eventuellt.

Professionellt som programmerare är det ganska långt mellan varven som jag upplevt detta men nu de sista 1-2 åren har det hänt ganska ofta. Begrepp som
* händelsebaserat
* immutable
* functional
* reactive
* single responsibility
* continious delivery
* micro services
har allt gått som en blixtar genom mitt huvud.

Det är inte så att jag levt i en bunker isolerad från omvärlden. Det är inte nytt, men en förståelse för vad de faktiskt innebär och vad var de hör hemma har kommit till mig (hoppas jag i alla fall).

Den senaste blixten i allt detta är insikten att ingen av dessa är fantastisk i sig själv utan att de tillsammans bildar en helhet. En ganska radikalt annorlunda helhet än den vi är vana med men ändå en helhet som tar sin utgångspunkt i reaktion. Detta kanske motställt till den traditionella modellen som åtminstone i praktiken fokuserar på planering och förutsägelse.

tisdag 29 december 2015

Är transaktioner blott en historisk parantes?

Jag har haft förmånen att få jobba med folk med erfarenhet ett antal gånger, jag menar närmare 50 års erfarenhet av programmering. Det som jag ofta hör, när dessa erfarna personer beskriver hur de gjorde förr, är det vi försöker att åstadkomma nu. Vi har bara varit ute på en utflykt, en normaliserad och transaktionstät utflykt, men just bara en utflykt.

Min tes är att någon gång i samband med att vi fick tillgång till RDBMS så slutade vi hantera två viktiga aspekter av vår programvara, tid och felhantering.

När man förr tog en fil (eller två) som indata till sitt program körde sitt program och producerade en ny fil var det data man hade i praktiken immutable. Om man upptäckte ett fel i programvaran kunde man kör det uppdaterade programmet utifrån de gamla filerna. Om man sparade sina filer hade man ett arkiv över alla förändringar man gjort på sitt data. Tiden var kanske inte lika mycket "up your face" som den är i eventsourcing, men den fanns där. Att modellera med tid på ett normaliserat sätt är ingen barnlek någonstans, för beroende på vilket delsystem som körs har de olika och ofta motstridiga krav som är väldigt svåra att slå ihop.

Vilket leder oss till nästa del av min tes. Förr, när man hade kört ett jobb och kontrollerade om det gått som det skulle, då fick man hantera vad som skulle hända. Om något gått fel tex fick någon besluta om att köra jobbet en gång till, tillkalla utvecklaren eller kanske till och med börja om från en tidigare tidpunkt. Det är lite som att lägga ett meddelande på en kö, man får välja hur man vill hantera om något gått fel, tex göra omskick, låta meddelandet dö, eller notifiera tjänsten som skickade meddelandet. I vilket fall är detta något som måste hanteras.

I dagens system tappar vi bort tiden eftersom vi glatt skriver över och raderar värden i vår databas utan information om vem, när eller varför. Om något går fel gör vi en rollback och tappar all information om vad som gjordes. Smidigt många gånger, men våra system är inte så flexibla på att möta nya krav och vår kompetens i hur man hanterar olika problemsituationer är låg.

Med tekniker som eventsourcing och microservices behöver vi återigen lära oss att leva utan den alltid närvarande transaktionen och vi måste lära oss att hantera problemsituationer på fler sätt än att rulla tillbaka en transaktion.