Event Sourcing, Domain Driven Design, and Command Query Responsibility Segregation – we hear all of these technologies used together frequently, but how do they actually work together? How do you manage complex co-ordination in a CQRS system?
In this talk, we will discuss a real world example of DDD with ES and CQRS written in F# - a functional first language on the .NET Framework. We’ll take a deep dive into the F# algebraic type system that constructs the domain model. Also, the explanation of the abstract notion of a DDD aggregate root compared to the CQRS implementation of an aggregate root. Finishing with how sagas and triggers facilitate poly-aggregate communication.
2. Agenda
• Overview of my journey into CQRS, ES, and F#
• Explore different patterns, practices and architectures
• 4 Segments
1) Event Sourcing
2) F#
3) Domain Driven Design
4) CQRS
• Disclaimer:This is what I’ve found works (or doesn’t) for us.
• Fast paced, will be covering a lot of information
3. Traditional Monolithic System
• Concurrency issues (Locking)
• CRUD Design
• Multiple Models
• Lacking developer discipline
• Typically not very scalable
Client
Model-View-Controller
RDBMS
4. CQRS/DDD/ES System
Client
ReSTful API
Command Model
Consumes
Writes
Query Model
Event
Store
Denormalized
Projection
Publishes
Reads
• Reads/Writes Segregated
• Concurrency Handling
• Clear separation of concerns (Read
vs Domain Model)
• Requires developer discipline
• High-throughput, scalable
5. Part One
“A way of representing state by storing the
history of the application’s state”
What is Event Sourcing?
6. What is an Event Store?
An immutable append-only transaction log.
Stock
Traded
Account
Updated
Stock
Traded
Account
Updated
Account
Updated
Time
7. RDBMS vs ES (Event Sourcing)
Relational Database Event Sourcing
State Current State
Tables Streams
Schemas Buckets
8. … what is Event Sourcing? (Cont.)
• Event Sourcing is a practice
• Persistence occurs in an “event store”
• Related events compose an “event stream”
• Streams are in chronological order
• Capability to project / rehydrate models
• Majority of RDBMS use a transaction log behind-the-scenes
9. What is an event?
• Events are state delta’s
• Events are immutable
• Transient or persisted
• Wrapped in a message (Header, Payload)
• Possibly consumed by 3rd parties
• Can be classified as a Domain, Infrastructural or System event
• Most events are past-tense behaviors of the domain (Ex: StockTraded)
10. What does an event look like?
• Domain Event Example (In F#):
12. Event Stream
• Event Stream : Grouping of related events
Stock
Traded
Account
Updated
Stock
Traded
Account
Updated
Account
Updated
Time
100101101 100100 Stream ID
13. Functionalities of aTransaction Log
• Slice stream
Contiguous subset of the stream
• Probe stream
Returns max score/offset of stream used for concurrency/state version management
• Append stream
Writes to the end of a stream
• Scan stream
Returns a specific subset of the stream (example: scan all “account updated”)
• Get stream
Returns all events from a specific stream, typically used for model rehydration
14. Rehydration
• The process of querying an event stream (GET) and “applying” it to the
model.
• Allows deterministic rehydration to a given point in time, commonly;
“Current State”
15. Projections
• Denormalized representation of the model
• Eventually consistent to the write model
• Projections are typically aligned to a specific screen on the UI
• May be organized by Aggregate
Read Model Event Read Model
16. F#
• F# is a mature, open source, cross-platform, functional-first programming
language.
• Why F#? (With DDD & ES)?
• Self documenting, expressive code
• The type system (algebraic, composable) prevents incorrect state
• Immutable out-of-the-box (Structural equality for value types)
PartTwo
18. F# Competitive Advantage
• The code serves as a self-documenting ubiquitous language
• WAY LESS CODE!! Once you learn it
• You can design your domain model to not allow incorrect states at compile
time
• Forced to handle errors (at compile time)
• No nulls! (Alternatives such as Options<‘T> and Choice<‘T1,’T2..>)
19. Domain Driven Design
• What is DDD?
• When and why DDD?
• What it provides you and your team?
PartThree
20. Bounded Contexts
• One large model vs. Bounded Contexts
• Can be aligned to an autonomous service
• Can’t start a DDD project without a BC (Bounded Context)
Trading Hedging
Accounting Management
22. Values
• No identity
• Immutable
• Structurally equatable
• Explicit type (primitives -> domain concept)
• May have localized behavior
23. Aggregates
• Abstract notion of
domain types
• Collection of entity
and value types
• Not-concrete
• Load/save aggregates
24. Aggregate Roots (DDD Context)
• All interaction with the aggregate (entities and values) goes through the
aggregate
• An AR is an Entity
• Manages consistency within the aggregate (all state change)
• Not to be confused with CQRS Aggregate root
25. Sagas
• Responsible for long-running business processes , “workflows”
• Allows for eventually consistent communication between aggregates
• Consume domain events, fire commands
• Events may be transient
TradeOrderCreated TradeExecuted TransactionRecieved
28. ReSTful API
HTTPVerb API Action
GET Queries the Read Model
POST Command on Queue -> (Create Command)
PUT Command on Queue -> (Update Command)
DELETE Command on Queue -> (Delete Command)
API Request
API Command
Command Handler
29. Commands
• Instantiated in the API
• No validation is performed
except for deserialization
• Placed on the queue to go
to the Handler
30. Triggers
• API Commands are mapped to triggers in the Command Handler
• Triggers are granular domain actions.When fired against the Aggregate
root, yield an event. (Fire : ‘state-> ‘trigger -> ‘event)
• Allow for explicit pathways of state change (Business rules, clear model)
33. Events
• Domain events represent the delta state change of the model
• The “Fire” function on an Aggregate root yields an event
• Events are serialized and stored in the event store
• Once persisted, they’re broadcasted to interested parties
34. Event Handlers
• Consume events dispatched from the Event Store
• Commonly used for:
• Updating the Read Model
• Notifying a 3rd party system
• Sagas
35. CQRS Aggregate Roots
• Gatekeeper for:
• Triggers interacting the with Aggregate
• Model Rehydration (Events)
37. Sagas,Triggers, and Poly-Aggregate
Communication• Sagas
• Provide an eventually consistent way of communicating between aggregates
• Best used when the process :
• Is “long running” (greater than a few seconds)
• Has a lot of business rules
• Interacts with 3rd party systems
• Trigger Pattern
• Provide a consistent way of multiple aggregates communicating at the same time
• Best used when:
• Two or more aggregates need to be validated/interact atomically
• Triggers are still used with one aggregate at a time!
38. Projections
• Denormalized representations of the domain model
• Typically correlate to 1) One UI screen 2) An aggregate
• Very similar to domain model rehydration (Apply: ‘state -> ‘event -> ‘state)
• Eventually consistent. Should not be used on the “Command/write side”
• Can be different than the write model
39. Read Model Query Cache Projection
Event Handlers
Push to ->
API GET->
40. • geteventstore.com
• NEventStore (++ CommonDomain)
• Domain Driven Design by Eric Evans
• Fsharp.org
• GalaxE Solutions (@GalaxESolutions)
• QuickenLoans (@QLTechnology)
• Matt Hawkins (@MattCHawkins)
Still Interested?
Hinweis der Redaktion
-Welcome to Real World Event Sourcing and CQRS
-Matt Hawkins, Consultant @ GalaxE Solutions – primary client Quicken Loans Capital Markets
Talk Summary, Agenda, Goal
Poll of the Audience
Why am I an advocate?
-This is Segment 0 -> brief introduction to topics covered so you have context into what I’ll be speaking about
-Comparison of Monolithic vs CQRS system
-
Overview of the architecture
Technologies chosen
Dive into all areas brifly, tie back to talk plan
Talk real world example vs what I’ll be showing
Deterministically audit data
No-loss biz case
-DDD is an approach to software development for complex systems, or where you can gain a competitive advantage from a biz perspective. Invented by Eric Evans
Not a silver bullet, a lot is obvious once you read it but it is a learning curve
Crafstmanship, focus on the BIZ,
-Ubiqitous language
Your team:
Everyone has a deep focus on the “domain model”, in CQRS, there is one “write model”
Everyone speaks the same colloquialisms and language around the domain
Designed for evolution and a focus on craftsmanship
Final goal : to build better software
-What would ordinarily be a very large model, is broken into bounded contexts
-Bounded contexts are typically by division/organization/domain focus (different people)
-May have different rules or language
-Their systems may evolve differently over time
-Two bounded contexts may speak the same WORDS but have different meanings
-More management from a development perspective
Basically separating the reads and writes
Pairs well with DDD and ES
High throughput/Very fast reads
Separtion of responsibility
Not a silver bulled
PUTs to multiple triggers
PATCH this logic may be handled in the API
Sagas are a model in themselves, they orchestrate the process and can be more robust than tirggers
You