mandag 28. september 2009 NNUG Greg Young Event sourcing
Greg Young er et kjent navn innen Domain-Driven Design. For tiden er han frivillig hjemløs og "arbeidsløs", og reiser rundt i verden og holder foredrag og kurs mens han forsøker å skrive bok. Nå er han i Norge, og sist onsdag hadde vi gleden av å ha ham som gjest på NNUG i Bergen.
Først holdt Greg en liten apell han kalte "The Great Failure". Han sier at det overskyggende flertall av systemer vi lager i softwarebransjen i dag er CRUD applikasjoner. Vi har lurt våre kunder til å tro at det er det de vil ha – mens systemen gjør brukerne langt mindre effektive enn det de kunne ha vært.
Årsaken til dette er den posisjonen vi har gitt relasjonsdatabasen, som vi bruker langt mer enn vi burde. Vi burde bry oss mer om hvilke handlinger brukerne våre skal utføre, om intensjonen bak handlingene. Vi burde designe software'n basert på adferd, og modellere adferden eksplisitt. Dette er noe av motivasjonen bak DDD, og spesielt den formen for DDD som Greg står for.
Deretter fortsatte han med å gi en innføring i noen sentrale elementer innen DDD – først og fremst Aggregate roots og Bounded Context – slik at publikum ikke skulle falle helt av i den siste og mest spennende sesjonen…
…som omhandlet noen av de nyvinningene som har kommet til DDD i årene etter at Eric Evans skrev den berømte boken, nyvinninger som Greg Young er en av personene bak. Jeg gjør et tappert forsøk på å oppsummere hva han snakket om; det vil ikke bli en erstatning for å høre på Greg selv, men kanskje en god "teaser". De fire konseptene han introduserte, som alle henger mer eller mindre sammen, var:
Dette dreier seg om å modellere endringer i datamodellen eksplisit. "Make the implicit explicit", sa han gjentatte ganger. Han eksemplifiserte dette bl.a. med en prosess for en webshop:
Først oppretter man en handlevogn – det er én handling. Deretter legger man kanskje til 2 varer i handlevognen. Det er en ny handling, og representeres ved et state-objekt med de to varene. Deretter bestemmer man seg kanskje for å fjerne en av varene. I en normal CRUD app ville man gjort dette som en update av handlevognens innhold, og da ville man ha mistet viktig informasjon, som at det først var lagt til to varer. Greg ville ha laget et nytt state-objekt som representerte handlingen "å fjerne en vare".
På den måten er audit-loggen bygget inn i hvordan systemet fungerer. Og man kan senere "spille tilbake" alt som har skjedd. Greg argumenterte meget godt for hvorfor dette er en fremgangsmåte som gir mening for mange systemer.
Event storage henger sammen med det forrige punktet: Greg snakket om å designe software med en "write once" arkitektur, dvs bruk av en add-only datamodell, hvor updates ikke er mulig. Den fullstendige tilstanden til modellen lagres ikke i basen – i stedet lagrer man serien med tilstands-endringer, som gir nå-tilstanden når de spilles av i riktig rekkefølge.
Dette vil bl.a. løse alle samtidighetsproblemer som normale CRUD-systemer sliter med, fordi to prosesser aldri behøver å skrive til samme record. Dessuten kan det garantere at audit'en er 100% riktig (om state-objektene lagres til et write once medium).
Greg bruker kun to tabeller for å persistere sin domenemodell: Den første tabeller lagrer aggregate roots (samling med relaterte objekter) i et serialisert format, og de lastes alltid sammen. Den andre tabellen inneholder events – dvs. tilstands-endringer. Når en enumerasjon av events lastes opp og leveres til aggregatet, spilles de av internt, og aggregatet får dermed riktig nå-tilstand.
Command-query separation (CQS) er et generelt prinsipp vi kjenner fra Bertrand Meyer, som sier at metoder enten skal være en kommando eller en spørring. Helt konkret betyr dette at en hvilken som helst metode enten endrer tilstand (objektets state eller har andre effekter som disk IO eller lignende) eller returnerer noe. CQS er f.eks. et av prinsippene Uncle Bob trekker frem i Clean Code, og jeg forsøker å følge det i all kode jeg produserer.
I denne sammenhengen betyr CQS noe mer. Greg snakker om å dele systemet en konstruerer i to deler: én del som er skreddersydd og optimalisert for å hente ut data, og en annen del som er designet for å utføre handlinger og endre data. Query/read-delen av systemet kan holdes tynt, og leverer rett og slett DTO'er (data transfer objects). Det er i command/write-delen av systemet at Greg vil benytte prinsippene i Domain-Driven Design – god objektorientering er "overkill" i read-delen, og kommer mye bedre til sin rett i et system som kun skal håndtere kommandoer.
Dette dreier seg om å skalere DDD. I arkitektur-tegningen over ser vi hvordan et system er delt i to delsystemer – ett for reads (query) og ett for writes (commands). De kunne brukt den samme datakilden, men ved å gi dem hver sin database bryter man den sterke avhengigheten mellom dem. Read-systemet henter endringer i Write-systemet asynkront (pull i stedet for push). Vi har dermed introdusert "relaxed consistency" (også kalt Eventually consistant) – og dataene vil ikke være korrekte i et hvilket som helst øyeblikk.
Det finnes et teorem som kalles CAP, som sier at et system kan ikke ha høy konsistens (Consistency), tilgjengelighet (Availability) og skalerbarhet (Partition-tolerance) samtidig. Ved å redusere konsistensen bare bittelitt kan vi derimot øke den potensielle skalerbarheten og tilgjengeligheten ganske mye. Det er derfor Greg fokuserer på SLA'er (Service Level Agreements). Han sier vi bør definere hva som er akseptabel SLA for alle operasjoner i det totale systemet vi designer, og bruke det til å dele opp i mindre systemer som kommuniserer asynkront.
På denne måten er vi heller ikke lengre avhengige av det svakeste leddet – ett system kan gå ned uten at resten blir påvirket, fordi vi følger en pull-modell. Dette har også mye til felles med best-practise SOA.
SLA'ene vil også fortelle oss hva som er de viktigste delene av systemet vi bygger. Der hvor vi har de strengeste kravene til oppetid og respons setter vi inn den største innsatsen. Greg påpeker at man som regel kan operere med avslappet konsistens mellom de fleste bounded contexts. Derimot vil vi måtte behøve å etablere kompanserende handlinger for å håndtere det at dataene ikke nødvendigvis er up-to-date til enhver tid.
NNUG Bergen tilrettelegger nå for et 2-dagers kurs med Greg Young hvor du får mulighet til å lære denne skalerte DDD-modellen. Dette er en unik mulighet til gi-bort-pris som jeg må innrømme frister veldig mye. Jeg jobber nå på et system som har mye til felles med det Greg har erfaring med, og jeg tror disse teknikkene kunne tilført nyttig kunnskap som over tid kunne tatt arbeidet vårt opp på et nytt nivå. Men det ser desverre ikke ut som om vi er i en sitasjon hvor teamet vårt kan gripe denne muligheten akkurat nå.
Til slutt noen linker: Greg Young blogger på codebetter.com. Greg har også holdt presentasjonen "Unleash Your Domain" andre steder enn på NNUG, og du finner den blant annet på infoQ. De har også gjort tilgjengelig et intervju med Greg, hvor han snakker om de samme tingene. For mer informasjon om DDD ville jeg startet på domaindrivendesign.org.