ES, CQRS & DDD: Lessons Learned (and walls bumped into)
Gitte Vermeiren | @GitteTitter
One does not simply
Use ES, CQRS & DDD
UI
Commands
Command Bus
Command
Command Handler
Domain
Model
Domain
Model
Domain
Model
Repository
Event Store
Aggregates
Events
Event Handler
Data
Thin Data Layer
Query DTO
Event Bus
Events
Person
Dossier
Payment
TechnicalInvestigation
DocumentGroup
Task
TaskClosedEvent
TaskPerformedEvent
DocumentRenamedEvent
TaskCreatedEvent
DocumentJudgedEvent
DocumentAddedToDocumentGroupEvent
DocumentMovedEvent
DossierApprovedForPaymentEvent
DocumentPrintedEvent
https://github.com/MarkNijhof/Fohjin
Problem 1
“Every ‘dossier’, ‘scan’, ‘decision’, ... Should
have a unique incremental number”
UI
Commands
Command Bus
Command
Command Handler
Domain
Model
Domain
Model
Domain
Model
Repository
Event Store
Aggregates
Events
Event Handler
Data
Thin Data Layer
Query DTO
Event Bus
Events
Use an
autoincrement
column?
Use a
‘DossierNumberGenerator’
DossierNumberGenerator
_highestNumber = 0
1. GenerateNext
2. DossierNumberGeneratedEvent
3. onDossierNumberGenerated
_highestNumber ++;
DossierNumberGenerator
_highestNumber = 0
onDossierNumberGenerated
_highestNumber ++;
DossierNumberGeneratedEvent
DossierNumberGeneratedEvent
DossierNumberGeneratedEvent
Replay
Repository.GetById<DossierNumberGenerator>(id);
UI
Commands
Command Bus
Command
Command Handler
Domain
Model
Domain
Model
Domain
Model
Repository
Event Store
Aggregates
Events
Event Handler
Data
Thin Data Layer
Query DTO
Event Bus
Events
Use a domain
service
Problem 2
DomainEvent
Id
AggregateId
Version
Raised
repo.GetById<Aggregate>(aggregateId);
Get/Store events based on
type, not on
eventproviderId?
Migrate those events
WIP
AnotherNewRefactoredAggregate
ANewRefactoredAggregate
anAggregate
SomeEvent
SomeOtherEvent
AndSomeMoreEvent
Migration
Process
SomeEvent
SomeOtherEvent
AndSomeMoreEvent
AndAFunkyEvent
https://github.com/vermegi/Eventstream.Migratorhttps://github.com/NEventStore/NEventStore.Migrations
Event Store
Event Store
Read the entire event stream Save the entire event stream
UI
Commands
Command Bus
Command
Command Handler
Domain
Model
Domain
Model
Domain
Model
Repository
Event Store
Aggregates
Events
Event Handler
Data
Thin Data Layer
Query DTO
Event Bus
Events
Replay needed
Event Versioning with an
EventUpdater
AnAggregate
_somePrivateStuff = 0
onSomeEvent:
_somePriveStuff = somevalue;
SomeEvent
AnotherEvent
AndAnotherEvent
Replay
Repository.GetById<AnAggregate>(aggregateId);
SomeEvent
AnotherEvent
AndAnotherEvent
Update
Repository.GetById<AnAggregate>(aggregateId);
SomeUpdatedEvent
AnotherEvent
AndAnotherEvent
AndAnotherEvent
Problem 3
AnAggregateSnapshot
Repository.GetById<AnAggregate>(aggregateId);
_version = 666
SomeEvent
Version = 667
AnotherEvent
Version = 668
AndAnotherEvent
Version = 669
AnAggregate
_somePrivateStuff = 0
onSomeEvent:
_somePriveStuff = somevalue;
Replay
Problem 4
Hard to use in debugging
Hard to do data updates
Hard to query
Problem 5
AnAggregate
_somePrivateValue = 0
DoSomething
onSomethingHappened
_somePrivateValue = something;
DoSomething
SomethingHappenedEvent
UI
Commands
Command Bus
Command
Command Handler
Domain
Model
Domain
Model
Domain
Model
Repository
Event Store
Aggregates
Events
Event Handler
Data
Thin Data Layer
Query DTO
Event Bus
Events
Hard to do data
updates
Reuse the same
logic
Do it functional
Problem 6
And for the good news?
Some final thoughts ...
VISUG Partners

DDD, CQRS & ES lessons learned (Gitte Vermeiren)