Presented in dotNetZone.gr Meetup #4. Goes through basic DDD concepts, recaps on CQRS, discusses when async messaging should be implemented and shows how with MassTransit.
4. DDD
DOMAIN MODEL
▸ exists in domain layer
▸ reflects structured knowledge about the domain
▸ ubiquitous language
▸ agreed/shared with domain experts
▸ typically implemented as a SOLID - OO model
▸ “technology” free !
5. DDD
DOMAIN STRUCTURE 1/2
▸ Entities
▸ id
▸ constant throughout its lifecycle
▸ mutable
▸ Value Objects
▸ no id
▸ immutable
▸ diff state = diff object
▸ offloading logic from entities
6. DDD
DOMAIN STRUCTURE 2/2
▸ Domain Services
▸ stateless
▸ behaviour that cannot be modelled with Entities, Value Objects
▸ Domain Events
▸ immutable
▸ timestamped
▸ ref to entities
7. DDD
AGGREGATE
▸ object graph of entities and value objects
▸ single entity is its root
▸ global identity
▸ external entities ref ONLY to the aggregate root
▸ root enforces invariants
▸ consistency boundary
20. CARGO TRACKER
REFACTORING - DELIVERY HISTORY
▸ “leaves Delivery History with no persistent state”
▸ “no real need to keep it around”
▸ “we could derive Delivery History itself whenever it is
needed to answer some question”
21. CARGO TRACKER
REFACTORING - HANDLING EVENT AGGREGATE
▸ HandlingEvent Aggregate:
▸ no domain logic (anemic)
▸ only repository + event class
▸ repository servicing query needs of other aggregates
34. CQRS RECAP
SYNC PROCESSING
▸ single process (e.g. Web App)
▸ decreases availability
▸ if process is UI affects UX
▸ in-process event dispatcher for decoupling
▸ rely on built-in framework facilities
▸ immediate consistency
35. CQRS RECAP
ASYNC PROCESSING
▸ multiple processes (e.g. WebApp and WorkerApp)
▸ higher availability, scaling out
▸ consistency eventual
▸ typically implemented with async messaging
▸ message bus
▸ in-process event dispatcher allows for applying selectively
36. CQRS RECAP
TYPICAL SYSTEM with CQRS + ASYNC PROCESSING
/ *
-BBB
3
B BB #
/ A A *
3 BB # 3 A
A BC A B A C A C B BC C
B 2 3
AB BCB BC C CB
B B A B B CB
C
B BB #
B 3B C 2 3 A B C A 3 3
. 3 - 3
C
2 B BC C#
/ A A * (
3 A A
A 2 BB C
3 AB#
C A 2 BB# C
B B2A A#
/ A A * )
2 ACB CB
C A 3 3
2CB 3 AB BCB
/A C 3
38. ASYNC MESSAGING
MESSAGE BUS 1/2
▸ frameworks: NServiceBus, MassTransit, Rebus etc.
▸ transports: RabbitMQ, Azure Service Bus etc.
▸ at least-once delivery
▸ FIFO
▸ reliable messaging
▸ automatic transport configuration setup
▸ pub/sub, send/receive
39. ASYNC MESSAGING
MESSAGE BUS 1/2
▸ frameworks: NServiceBus, MassTransit, Rebus etc.
▸ transports: RabbitMQ, Azure Service Bus etc.
▸ at least-once delivery
▸ FIFO
▸ reliable messaging
▸ automatic transport configuration setup
▸ pub/sub, send/receive
40. ASYNC MESSAGING
ASYNC & RELIABLE MESSAGING
ALL=CA .KI AK
N ELDAK A AK AM
N L KE AK ( A AE AK
AM
N L KE AK )
1P D= CA -
NANA ( NANA )
1P D= CA . R
)
-/3IK1KKIK
(
A
-/3IK
=
LC A E AKQ EL 142-.41 ( # , 2B
LC EL IM - A Q MDA .KI AK =
1KKIK EL K=ELA E MDA A AK
LC A E AKQ EL 142-.41 ) # , 2B LC EL IM - A IK
= A Q MDA A AE AK MDA LC LM=QL E MDA NANA
LC A E AKQ A MI
A # EL - / ,
A AK EL I A =BMAK
CAMME C MDA -
LC A E AKQ EL
142-.41 # ,
NANAL = A
AKLELMA M = KILL
KI AK KALM=KML
- = EM # 1 - 41
AAEA
41. ASYNC MESSAGING
MESSAGE BUS 2/2
▸ connection management
▸ persistent sagas/process managers
▸ retrying policy on subscriber/receiver errors
▸ alarm service
▸ (de)serialization
66. IMPLEMENTATION
MASSTRANSIT RETRING FLOW (SIMPLIFIED)
1. message deserialised
2. identity consumer from message type
A. if consumer identified
‣ run handler in try/catch
‣ on exception check retry policy
‣ either retry on ignore
B. if consumer is NOT identified (TbC)
72. IMPLEMENTATION
EVENT DISPATCHER 1/2
▸ wires SYNChronously (in-process) command with event handlers
▸ is the “Emitter”
▸ wired handlers can be
▸ an actual, in-process one (e.g. read model update)
▸ a forwarder (event->message + publish) to the bus
▸ both
▸ even for the same event
▸ infra free implementation
75. IMPLEMENTATION
EVENT EMITTING/PUBLISHING
▸ as with Commands, Events should use domain structures
▸ IEventEmitter abstraction similar to ICommandIssuer
▸ MassTransit implementation with Bus.Publish<T>
▸ Converts Events to Messages (TbC)
78. IMPLEMENTATION
EVENT SUBSCRIBING / BOOTSTRAPPING MASSTRANSIT
▸ bootstrapping identical to command receiving
▸ need a Consumer<T>
▸ translates the message to event
▸ instantiates and invokes event handler
85. BEST PRACTICES
MESSAGE DESIGN
▸ messages are POCOS. (period)
▸ do NOT reuse domain structures
▸ SERIOUS danger of message loss
▸ type repetition and mapping are unavoidable
▸ Automapper FTW !
▸ messages might change (aka message versioning)
▸ subscribe to interfaces
▸ ensure correct version or serialiser assembly deployed
▸ JSON .NET
86. BEST PRACTICES
SYSTEM ARCHITECTURE
▸ apply selectively not globally
▸ always forward (i.e. publish) the events
▸ bounded context interface
▸ rely on the retrying facilities
▸ idempotency
▸ fence “expensive” services
▸ perhaps even with sync send/receive (e.g. Routing Service)
87. BEST PRACTICES
SCALING OPTIONS
▸ scale up: can invoke Message Handlers in parallel using a
ThreadPool = Round Robin
▸ bus.SetConcurrencyLimit
▸ scale out: “competing consumers”
▸ same EndPointID
▸ probable concurrency issues
▸ aggregate versioning !
88. BEST PRACTICES
HOUSE-KEEPING
▸ descriptive End Point IDs mostly for subscribers/receivers
▸ web_SERVER1_sender
▸ cmd_rec_worker
▸ evt_sub_booking_reporting
▸ evt_sub_shipping
▸ monitor transport
94. CHALLENGES
EVENTUAL CONSISTENCY
▸ heavily affects UI/UX
▸ contradicts user mentality
▸ need to notify on command handling error
▸ makes UI implementation more complex
95. CHALLENGES
IMPLEMENTATION-RELATED
▸ a LOT of type repetition
▸ more physical processes
▸ changes MIGHT need orchestration
▸ concurrency issues
▸ transport = additional infra
97. RESOURCES
DDD
▸ Domain Driven Design by Eric Evans
http://amzn.to/2uhbOSc
▸ Patterns, Principles and Practices of Domain-Driven Design by
Scott Millett
http://amzn.to/2hsNbLg
▸ Effective Aggregate Design (3 Part Series) by Vaughn Vernon
https://vaughnvernon.co/?p=838
▸ Awesome DDD by Nick Chamberlain
https://github.com/heynickc/awesome-ddd
98. RESOURCES
CQRS
▸ CQRS Journey by Microsoft Patterns & Practises
cqrsjourney.github.io
▸ CQRS by Edument
cqrs.nu
▸ Clarified CQRS by Udi Dahan
udidahan.com/2009/12/09/clarified-cqrs
99. RESOURCES
SAMPLES
▸ Cargo Tracker
▸ github.com/citerus/dddsample-core
(Java) by Citerus AB
▸ github.com/SzymonPobiega/DDDSample.Net
(.ΝΕΤ) by Szymon Pobiega
▸ CQRS, The example - Mark Nijhof
leanpub.com/cqrs