Categories
Teknik

Ge din kod mer affärsfokus med CQRS

CQRS är ett hett ämne hos systemutvecklare just nu. Nedan försöker vi förklara nyttan från ett övergripande perspektiv, med utgångspunkt i affärsverksamheten. Citerus konsult Mattias Holmqvist beskriver i denna artikel CQRS från hög höjd och pekar på vilka möjligheter det ger att öka fokus på affärsnyttan i ett utvecklingsprojekt.

CQRS är ett hett ämne hos systemutvecklare just nu. Nedan försöker vi förklara nyttan från ett övergripande perspektiv, med utgångspunkt i affärsverksamheten.  Citerus konsult Mattias Holmqvist beskriver i denna artikel CQRS från hög höjd och pekar på vilka möjligheter det ger att öka fokus på affärsnyttan i ett utvecklingsprojekt.

mattias-holmqvist

Det traditionella systemet

Vi börjar vårt utforskande genom att titta på en skiss av det traditionella systemet, här representerat av en typisk lagerarkitektur med en databas i ena änden och ett API som våra användare kan anropa i andra änden. Vår skiss är givetvis förenklad men poängen är att all kommunikation går genom samma API, samma affärslogik och information lagras och hämtas ur samma databas.

CQRS bild 1

Vad är CQRS?

Förutom att vara svårt att komma ihåg och stava så är själva idén bakom CQRS varken komplicerad eller någonting nytt. Det hela handlar om att separera den del av systemet som svarar på frågor från den del som utför tillståndsförändringar genom att ta emot kommandon. Originaltanken härstammar från Bertrand Meyers CQS (Command Query Separation). Med CQS delar vi upp funktioner och metoder (de minsta beståndsdelarna i applikationer) genom att klassificera dem som frågor eller kommandon.

CQRS Bild 2Steg 1 – uppdelning av affärslogik och dataprojektion

Om man tillämpar tankarna kring CQS på systemnivå istället för på metod/klassnivå uppnår man CQRS*. Vi försöker visualisera detta genom att förändra vår skiss:
Det API som nu hanterar kommandon kommunicerar med domänmodellen för att förändra systemets tillstånd. Det är här systemets beteende implementeras. För de situationer som kräver att vi presenterar data för en användare kommunicerar vi med ett separat API och den delen av applikationen kan köras oberoende från domänmodellen. De två delsystemen delar fortfarande databas så vi har egentligen inte gjort någonting mer än att dela uppsystemet. Vi har nu ett CQRS-system i sin enklaste form.

Uppdelad datamodellCQRS bild 3

Man kan även dra separationen ytterligare ett steg genom att dela upp databasen – en databas för systemets “sanna” tillstånd och en databas för att hantera frågor. Med denna uppdelning får vi möjlighet att förbereda datat för frågor i databasen som är tillägnad läsning.

Att förbereda datat innebär i praktiken att datat är lagrat i precis den form som klienten vill ha sitt svar, vilket förenklar utvecklandet av nya rapporter eller liknande presentationskod eftersom det blir enkla frågor mot databasen. Vi behöver heller inte oroa oss för att förstöra någon affärslogik när vi implementerar nya frågor. Experiment och utvärderingar blir billiga och enkla!

 

Vad är grejen?

Att dela upp systemet i två delar kan verka trivialt men samtidigt kan det se ut som att vi komplicerar saker och ting och man kan fråga sig varför vi gör detta överhuvudtaget.

Vi på Citerus gillar domändriven design. Många av oss har jobbat med DDD i flera år och vi tar med oss de tankarna in i de våra konsultuppdrag varje dag. Från då jag först hörde talas om DDD har både koncepten och tekniken utvecklats och de fundamentala och grundläggande idéer som Eric Evans presenterade har förädlats.

Några av de viktigaste elementen inom domändriven design är att fokusera på kärndomänen och att se till att verksamhetsexperternas språk finns representerat i koden och att alla inblandade i utvecklingen använder ett gemensamt språk. Vi vill helt enkelt bygga mjukvara som ger affärsnytta på riktigt. CQRS är ett effektivt sätt att förenkla och strukturera dessa tankar.

Min erfarenhet är att med tiden bygger man ofta in optimeringar för presentationslogik i domänmodellen och istället för att fokusera på affärslogik får vi en blandning av komplex teknik och otydligt beteende. När vi applicerar CQRS flyttar vi den kod som hanterar kärnverksamheten till den del av systemet som tar emot kommandon och kan då hantera komplex affärslogik på ett ställe, utan förvirrande optimeringskod som inte har med affärslogiken att göra.

Vi ser också till att använda verksamhetens språk när vi utformar våra kommandon för att fånga syftet med en förändring i systemet. Kanske lägger man en order innan den aktiveras. Förmodligen använder verksamheten den typen av verb och inte endast skapa, uppdatera och ta bort, vilket annars är vanligt förekommande i implementationskod. På detta sätt får denna del av systemet ett fokus och en tydlighet kring domänlogiken. Det blir lättare att prata om systemet med domänexperter när vi lyssnar på deras språk och låter det skina igenom i systemets kommandon.

Stödfunktioner såsom t ex rapportering hamnar i andra delar av systemet där vi hanterar frågor. Med CQRS kan vi enklare ta beslut om var i systemet olika krav kommer att slå och lättare planera samt dela upp vårt arbete. Vi minskar dessutom risken för buggar och problem som beror på olycklig sammankoppling i systemet. Vanliga exempel på dåliga symptom på detta är till exempel presentationslogik i domänmodellen eller duplicerad affärslogik.

Vad driver arkitekturell förändring?

Det är ju coolt att använda buzzwords och hänga med de senaste trenderna inom teknik. CQRS är en läskig förkortning som tilltalar tekniker då den är teknisk och dessutom svår att lägga på minnet. Skickliga utvecklare ser dock till att teknik och arkitektur inte innehåller häftiga förkortningar för sakens skull, utan fokuserar istället på att ge systemet den rörlighet och frihet som krävs när kraven från verksamheten kommer och pressen på leverans ökar.

Med CQRS kan vi skala upp läs-sidan utan att påverka skrivningarna till systemet. Vi kan göra förändringar för att möta icke-funktionella krav utan att riskera att förstöra prestandan i andra delar av systemet, vilket vi har stor risk att göra om både skrivningar och läsningar hanteras tillsammans och den enda datamodellen växer okontrollerat. Vi får möjligheter att bygga vidare på systemet utan att förståelse för systemets beteende minskar och utan att prestandan i redan implementerade funktioner tar stryk.

Även testning av systemet förenklas då vi kan vara säkra på att en läs-operation inte förändrar systemets tillstånd eller medför något oförväntat beteende. Att blanda läsningar och skrivningar medför också komplexitet i de verktyg vi använder för testning och installation vilket vi nu också kan göra oss av med.

Skörda frukterna av en ren och enkel domänmodell

Jag tycker att den viktigaste fördelen kommer av att ha domänmodellen på ett ställe i koden, där vi fokuserar på att lösa affärssidans problem. Med en domänmodell som endast hanterar beteende och på så vis kapslar in kärnan av verksamhetens krav och idéer kommer stor kraftfullhet och uttrycksfullhet. Det är intressant hur vi genom att ställa hårdare villkor på hur vi fokuserar vår domänmodell ökar möjligheten att fånga verksamhetens verkliga behov. Från detta öppnar det upp sig en värld av möjligheter kring utbyggnad och förändring av systemet som i många fall är omöjligt med en traditionell lagerarkitektur.

Det behöver inte vara en stor eller svår investering att bryta upp sitt system och närma sig en CQRS-arkitektur. För mig är CQRS (och även Event Sourcing) en ögonöppnare för hur man på ett praktiskt plan kan använda domändriven design och lyckas hålla tydligheten av verksamhetens språk i koden, utan att koden ruttnar över tid.

*(Command Query Responsibility Segregation, Greg Young)

Lär dig mer om CQRS och Event Sourcing

Leave a Reply

Your email address will not be published. Required fields are marked *