Introduktion til CQRS og event sourcing #3

I det forrige indlæg så hvordan vi kunne kode en Beetroot, som vi kunne sende en SqueezeCommand til. Når command’en blev processeret ville den kalde Squeeze(howMuch)-funktionen på rødbeden, som så ville emitte en BeetrootSquashed event hvis den stadig havde list saft i sig, og ellers ville den emitte en BeetrootCompletelyCrushed – så langt så godt!

Men vi mangler stadigvæk at få bragt lidt liv i det hele, og det er det vi skal kigge på i dette indlæg.

Command-processering

Udgangspunktet for alt hvad der sker i et Cirqus-baseret system er, at vi skal have fat i noget, der kan processere vores commands – og det er ikke så svært at få fat i sådan en, for du kan bare gøre sådan her:

var commandProcessor = new CommandProcessor(...);

hvor ... skal udfyldes med 3 afhængigheder:

  • IEventStore: En implementation af noget, der kan gemme og hente events (kan p.t. gøres i SQL Server, MongoDB og PostgreSQL)
  • IAggregateRootRepository: En implementation af noget, der kan hjælpe med at hydrere aggregate roots (findes p.t. kun i en “naiv” variant: En, der laver fuld hydrering hver gang der er behov)
  • IEventDispatcher: En implementation af noget, der gerne vil have mulighed for at arbejde videre på events i takt med at de bliver genereret (f.eks. til views/projektioner, integration til andre systemer, osv.)

Lad os starte med at bruge SQL Server som event store – det kan vi gøre sådan her:

var eventStore = new MsSqlEventStore("mssql", "Events", automaticallyCreateSchema: true);

forudsat at vi har en connection string i vores app.config med navnet “mssql”. Vores aggregate root repository hedder DefaultAggregateRootRepository og kræver et IEventStore for at kunne fungere (fordi den skal hydrere aggregate roots på baggrund af events):

var aggregateRootRepository = new DefaultAggregateRootRepository(eventStore);

Afslutningsvis skal vi stille med en IEventDispatcher, og der tager vi fat i en, der senere kan benyttes til at generere view-delen af vores system – den kræver et aggregate root repository fordi views skal kunne loade aggregate roots hvis de har brug for det:

var eventDispatcher = new ViewManagerEventDispatcher(aggregateRootRepository);

Hvis man sætter det sammen, så ser det således ud:

// ved opstart:
var eventStore = new MsSqlEventStore("mssql", "Events", automaticallyCreateSchema: true);
var repository = new DefaultAggregateRootRepository(eventStore);
var dispatcher = new ViewManagerEventDispatcher(aggregateRootRepository);

var commandProcessor = new CommandProcessor(eventStore, repository, dispatcher);

// først....
commandProcessor.Initialize();

// og så i resten af applikationens levetid:
commandProcessor.ProcessCommand(...);

og det er faktisk alt, hvad der skal til for at kunne komme i gang med at kode en rig domænemodel baseret på event sourcing – ikke så ringe, hvis du spørger mig 🙂

I næste indlæg vil vi kigge på hvordan man kan etablere en projektion af vores events: Et view, som holdes opdateret med events efterhånden som de bliver genereret. Stay tuned….

Share Button
The following two tabs change content below.
Profile photo of Mogens Heller Grabe

Mogens Heller Grabe

Software Developer af d60
Smidig .NET-håndværker, som svinger kodehammeren hos d60 om dagen og brygger open source om natten. Mine interesser indbefatter i særlig grad distribuerede systemer, messaging og moderne databaser, og teknologisk set er jeg velfunderet/-nedgravet i C# og .NET-land.
Profile photo of Mogens Heller Grabe

Nyeste indlæg af Mogens Heller Grabe (se alle)

Flattr this!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *