SlideShare a Scribd company logo
1 of 42
DDD South West 2An Introduction to CQRS approaches to system architecture @NeilRobbins neil@computer.org
Aims An overview of CQRS UI Command Handling View Handling How to write an Event Sourced DDD system The command handling bit
But first some code To Visual Studio!
What’s wrong with this?  public class Event     {         public string Name { get; set; }         public int Venue { get; set; }         public DateTime Date { get; set; }         public IEnumerable<Session> Sessions { get; set; }     }     public class Session     {         public PresentationPresentation { get; set; }         public string Location { get; set; }         public DateTime Time { get; set; }     }
But what about Queries? They’re just queries They support the UI which should provide a Decision Support System
Intentful UI Shopping Cart Service Command Command Ratings Service Command Command Product Images Service Command Command Command Buying Choices Service Offers Service Bought Together Service
Intentful UI Captures Intent Aligns with commands Uses the query infrastructure For display For decision support Commands should succeed Will contain logic, is typically rich
Some Slides Big picture & background stuff!
Façadelient Bus Commands Eventually Consistent Queries Handler
Subscriber Subscriber Publisher Subscribers Subscriber
ID : 123 Name : The Art of War Author: Sun Tzu ISBN: 1234ABCD5678 Event: BookIsbnChanged NewValue: 4321DCBA8765
…there are times when we don't just want to see where we are, we also want to know how we got there http://martinfowler.com/eaaDev/EventSourcing.html
Time to See Some Code You didn’t think I’d make you watch me type did you?
Coding for EventSourcing namespaceProgNetDemo { public classCatalogItem     {     } }
A Command Method namespaceProgNetDemo { public classCatalogItem     {  public void Retire()       	{         	}     } }
Some State To Change namespaceProgNetDemo { public classCatalogItem     { privatebool _retired;  public void Retire()       	{         	}     } }
Guard the Mutation namespaceProgNetDemo { public classCatalogItem     { privatebool _retired;  public void Retire()       	{ if (!_retired) thrownewInvalidOperationException();         	}     } }
Make the State Mutation A Domain Event namespaceProgNetDemo { public classCatalogItem     { privatebool _retired;  public void Retire()       	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));         	}     } }
Need an Identifier for the Aggregate public classCatalogItem { privatebool _retired; privateGuid_id;  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} }
Create the Event publicclassRetiredEvent { privatereadonlyGuid _id; publicRetiredEvent(Guid id)     { 		_id = id; 	} }
Need to be Able to Apply the Event public classCatalogItem { privatebool _retired; privateGuid_id;  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} }
Create a Base Class public classAggregateRoot  { protected voidApplyEvent(Event @event) 	{ 	} } We’ll need to handle more than just the one type of event!
Create the Event Type public classEvent { }
Have our RetiredEvent Inherit From the Base Type publicclassRetiredEvent : Event { privatereadonlyGuid _id; publicRetiredEvent(Guid id)     { 		_id = id; 	} }
Still Need to Mutate the State public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id;  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} }
Create a Method to Handle the State Change From the Event public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id;  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} private voidApplyRetiredEvent(RetiredEvent @event) 	{ 		_retired = true; 	} }
Done!? public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id;  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} private voidApplyRetiredEvent(RetiredEvent @event) 	{ 		_retired = true; 	} }
Need to Connect the Event with the Handler public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; publicCatalogItem() 	{ RegisterHandler<RetiredEvent>(ApplyRetiredEvent); 	}  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} private voidApplyRetiredEvent(RetiredEvent @event) 	{ 		_retired = true; 	} }
Allow Handlers to be Registered public classAggregateRoot  { protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ 	} protected voidApplyEvent(Event @event) 	{ 	} }
Create the Delegate Signature public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot  { protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ 	} protected voidApplyEvent(Event @event) 	{ 	} }
Need to Maintain the Registry public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot  { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ var castHandler =  		        DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); 	} protected voidApplyEvent(Event @event) 	{ 	} }
Delegate Adjuster:From Greg’s Blog public class DelegateAdjuster {     public static Action<TBase> CastArgument<TBase, TDerived>(Expression<Action<TDerived>> source) whereTDerived : TBase {         if (typeof(TDerived) ==typeof(TBase)) {             return (Action<TBase>)((Delegate)source.Compile()); } ParameterExpressionsourceParameter = Expression.Parameter(typeof(TBase),"source"); varresult = Expression.Lambda<Action<TBase>>( Expression.Invoke(                 source, Expression.Convert(sourceParameter, typeof(TDerived))), sourceParameter);         return result.Compile(); } }
Need to Maintain the Registry public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot  { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ var castHandler =  		        DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); 		 _handlerRegistry.Add(typeof(TEvent), castHandler); 	} protected voidApplyEvent(Event @event) 	{ 	} }
Need to Apply the Event Still public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot  { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ var castHandler =  		        DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); 		 _handlerRegistry.Add(typeof(TEvent), castHandler); 	} protected voidApplyEvent(Event @event) 	{ Action<Event> handler; if (!_handlerRegistry.TryGetValue(@event.GetType(), out handler)) 		{ throw newInvalidOperationException(); 		} 		handler(@event); 	} }
Need to Track Applied Events public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot  { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; private readonlyICollection<Event> _events; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event 	{ var castHandler =  		        DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); 		 _handlerRegistry.Add(typeof(TEvent), castHandler); 	} protected voidApplyEvent(Event @event) 	{ Action<Event> handler; if (!_handlerRegistry.TryGetValue(@event.GetType(), out handler)) 		{ throw newInvalidOperationException(); 		} 		handler(@event); 		_events.Add(@event); 	} }
All done now??? public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; publicCatalogItem() 	{ RegisterHandler<RetiredEvent>(ApplyRetiredEvent); 	}  public void Retire() 	{ if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id));     	} private voidApplyRetiredEvent(RetiredEvent @event) 	{ 		_retired = true; 	} } Could use a convention & just make the AggregateRoot declare which events it produces
Not Quite Need to Expose the events for persistence & publishing Put a GetChanges() method on the AggregateRoot base class Need to be able to rebuild the Aggregate from history Put a LoadFromHistory(IEnumerable<Event> events) method on the AggregateRoot base class Reapply the events Don’t track them as changes – overload apply event protected voidApplyEvent(Event @event, booltrackAsChange) if (add) _events.Add(@event); Possibly memento pattern for snapshoting See Mark Nijhof’s blog & sample code on GitHub
Back to the Whiteboard! Some more on Query Stores
Some Other Benefits of Event Sourcing Already We can build new stores for new services, we have the full set of available information ready We can rebuild stores for existing services We use the same mechanism for our Query Stores as we use for any other service in the Enterprise More Granular Service Boundaries More Explicit Boundaries We aren’t just restricted to storing the Events Can send Emails based on them Can perform Complex Event Processing … The worlds your Oyster, you have the RAW MATERIAL
Some Other Benefits of Event Sourcing Also A Very Provable Audit Log Very Simple Horizontal Scaling More Granular Service Boundaries More Explicit Boundaries Can Replay Events in Debugging Scenarios Suits Behaviour Based Testing & Outside-In Development
NO SILVER BULLETS The coding is the EASY BIT Don’t need a grand framework The thinking & conversations is the HARD BIT
Referenced Material/Links Greg Youngs: Course – http://bit.ly/gregscourse Blog – http://bit.ly/gregyoungsblog UdiDahans: Course – http://bit.ly/udiscourse Blog – http://bit.ly/udisblog Mark Nijhof’s sample code http://github.com/MarkNijhof/Fohjin

More Related Content

What's hot

Stay with React.js in 2020
Stay with React.js in 2020Stay with React.js in 2020
Stay with React.js in 2020Jerry Liao
 
A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesDavid Wengier
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo Ali Parmaksiz
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xTatsuya Maki
 
CDI do básico ao avançado
CDI do básico ao avançadoCDI do básico ao avançado
CDI do básico ao avançadoAlberto Souza
 
Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Payara
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Astrails
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql JOYITAKUNDU1
 
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy
 
Intro to React | DreamLab Academy
Intro to React | DreamLab AcademyIntro to React | DreamLab Academy
Intro to React | DreamLab AcademyDreamLab
 
Protocol-Oriented Networking
Protocol-Oriented NetworkingProtocol-Oriented Networking
Protocol-Oriented NetworkingMostafa Amer
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
 

What's hot (20)

Stay with React.js in 2020
Stay with React.js in 2020Stay with React.js in 2020
Stay with React.js in 2020
 
A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project Files
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
 
Introduction to android
Introduction to androidIntroduction to android
Introduction to android
 
CDI do básico ao avançado
CDI do básico ao avançadoCDI do básico ao avançado
CDI do básico ao avançado
 
Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
 
Easy Button
Easy ButtonEasy Button
Easy Button
 
React lecture
React lectureReact lecture
React lecture
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Android TDD
Android TDDAndroid TDD
Android TDD
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoC
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
Maze
MazeMaze
Maze
 
Intro to React | DreamLab Academy
Intro to React | DreamLab AcademyIntro to React | DreamLab Academy
Intro to React | DreamLab Academy
 
Protocol-Oriented Networking
Protocol-Oriented NetworkingProtocol-Oriented Networking
Protocol-Oriented Networking
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 

Viewers also liked

Event-driven architecture
Event-driven architectureEvent-driven architecture
Event-driven architectureAndrew Easter
 
Eventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDBEventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDBJacopo Nardiello
 
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)Michiel Rook
 
Event sourcing
Event sourcingEvent sourcing
Event sourcingRich Lee
 
From ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingFrom ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingEmanuele DelBono
 
TYPO3 Event Sourcing
TYPO3 Event SourcingTYPO3 Event Sourcing
TYPO3 Event SourcingOliver Hader
 
DDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkDDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkbanq jdon
 
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
The 6 Rules for Modernizing Your Legacy Java Monolith with MicroservicesThe 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
The 6 Rules for Modernizing Your Legacy Java Monolith with MicroservicesLightbend
 

Viewers also liked (12)

Event your life with Kafka
Event your life with KafkaEvent your life with Kafka
Event your life with Kafka
 
Event-driven architecture
Event-driven architectureEvent-driven architecture
Event-driven architecture
 
Eventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDBEventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDB
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
EventSourcing applied
EventSourcing appliedEventSourcing applied
EventSourcing applied
 
Event-sourcing avancé avec Scala
Event-sourcing avancé avec ScalaEvent-sourcing avancé avec Scala
Event-sourcing avancé avec Scala
 
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
CQRS & Event Sourcing in the wild (ScotlandPHP 2016)
 
Event sourcing
Event sourcingEvent sourcing
Event sourcing
 
From ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingFrom ActiveRecord to EventSourcing
From ActiveRecord to EventSourcing
 
TYPO3 Event Sourcing
TYPO3 Event SourcingTYPO3 Event Sourcing
TYPO3 Event Sourcing
 
DDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkDDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFramework
 
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
The 6 Rules for Modernizing Your Legacy Java Monolith with MicroservicesThe 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
 

Similar to An intro to cqrs

Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCaelum
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developersPavel Lahoda
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon Berlin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureAlexey Buzdin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureC.T.Co
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgetsvelveeta_512
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 
重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1Chris Huang
 
Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Paco de la Cruz
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEDarwin Durand
 
DWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A TutorialDWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A Tutorialjbarciauskas
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesAnkit Rastogi
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalDroidcon Berlin
 

Similar to An intro to cqrs (20)

Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptor
 
Why realm?
Why realm?Why realm?
Why realm?
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgets
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1
 
Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLE
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
DWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A TutorialDWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A Tutorial
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-final
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Jersey Guice AOP
Jersey Guice AOPJersey Guice AOP
Jersey Guice AOP
 

Recently uploaded

Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...
Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...
Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...lizamodels9
 
RE Capital's Visionary Leadership under Newman Leech
RE Capital's Visionary Leadership under Newman LeechRE Capital's Visionary Leadership under Newman Leech
RE Capital's Visionary Leadership under Newman LeechNewman George Leech
 
Pitch Deck Teardown: NOQX's $200k Pre-seed deck
Pitch Deck Teardown: NOQX's $200k Pre-seed deckPitch Deck Teardown: NOQX's $200k Pre-seed deck
Pitch Deck Teardown: NOQX's $200k Pre-seed deckHajeJanKamps
 
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCRsoniya singh
 
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...lizamodels9
 
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptx
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptxBanana Powder Manufacturing Plant Project Report 2024 Edition.pptx
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptxgeorgebrinton95
 
rishikeshgirls.in- Rishikesh call girl.pdf
rishikeshgirls.in- Rishikesh call girl.pdfrishikeshgirls.in- Rishikesh call girl.pdf
rishikeshgirls.in- Rishikesh call girl.pdfmuskan1121w
 
Tech Startup Growth Hacking 101 - Basics on Growth Marketing
Tech Startup Growth Hacking 101  - Basics on Growth MarketingTech Startup Growth Hacking 101  - Basics on Growth Marketing
Tech Startup Growth Hacking 101 - Basics on Growth MarketingShawn Pang
 
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service Jamshedpur
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service JamshedpurVIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service Jamshedpur
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service JamshedpurSuhani Kapoor
 
VIP Kolkata Call Girl Howrah 👉 8250192130 Available With Room
VIP Kolkata Call Girl Howrah 👉 8250192130  Available With RoomVIP Kolkata Call Girl Howrah 👉 8250192130  Available With Room
VIP Kolkata Call Girl Howrah 👉 8250192130 Available With Roomdivyansh0kumar0
 
2024 Numerator Consumer Study of Cannabis Usage
2024 Numerator Consumer Study of Cannabis Usage2024 Numerator Consumer Study of Cannabis Usage
2024 Numerator Consumer Study of Cannabis UsageNeil Kimberley
 
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756dollysharma2066
 
NewBase 22 April 2024 Energy News issue - 1718 by Khaled Al Awadi (AutoRe...
NewBase  22 April  2024  Energy News issue - 1718 by Khaled Al Awadi  (AutoRe...NewBase  22 April  2024  Energy News issue - 1718 by Khaled Al Awadi  (AutoRe...
NewBase 22 April 2024 Energy News issue - 1718 by Khaled Al Awadi (AutoRe...Khaled Al Awadi
 
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,noida100girls
 
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… Abridged
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… AbridgedLean: From Theory to Practice — One City’s (and Library’s) Lean Story… Abridged
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… AbridgedKaiNexus
 
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Progress Report - Oracle Database Analyst Summit
Progress  Report - Oracle Database Analyst SummitProgress  Report - Oracle Database Analyst Summit
Progress Report - Oracle Database Analyst SummitHolger Mueller
 
Non Text Magic Studio Magic Design for Presentations L&P.pptx
Non Text Magic Studio Magic Design for Presentations L&P.pptxNon Text Magic Studio Magic Design for Presentations L&P.pptx
Non Text Magic Studio Magic Design for Presentations L&P.pptxAbhayThakur200703
 
Keppel Ltd. 1Q 2024 Business Update Presentation Slides
Keppel Ltd. 1Q 2024 Business Update  Presentation SlidesKeppel Ltd. 1Q 2024 Business Update  Presentation Slides
Keppel Ltd. 1Q 2024 Business Update Presentation SlidesKeppelCorporation
 

Recently uploaded (20)

Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...
Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...
Call Girls In Kishangarh Delhi ❤️8860477959 Good Looking Escorts In 24/7 Delh...
 
RE Capital's Visionary Leadership under Newman Leech
RE Capital's Visionary Leadership under Newman LeechRE Capital's Visionary Leadership under Newman Leech
RE Capital's Visionary Leadership under Newman Leech
 
Pitch Deck Teardown: NOQX's $200k Pre-seed deck
Pitch Deck Teardown: NOQX's $200k Pre-seed deckPitch Deck Teardown: NOQX's $200k Pre-seed deck
Pitch Deck Teardown: NOQX's $200k Pre-seed deck
 
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR
(8264348440) 🔝 Call Girls In Keshav Puram 🔝 Delhi NCR
 
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...
Call Girls In Radisson Blu Hotel New Delhi Paschim Vihar ❤️8860477959 Escorts...
 
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptx
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptxBanana Powder Manufacturing Plant Project Report 2024 Edition.pptx
Banana Powder Manufacturing Plant Project Report 2024 Edition.pptx
 
Best Practices for Implementing an External Recruiting Partnership
Best Practices for Implementing an External Recruiting PartnershipBest Practices for Implementing an External Recruiting Partnership
Best Practices for Implementing an External Recruiting Partnership
 
rishikeshgirls.in- Rishikesh call girl.pdf
rishikeshgirls.in- Rishikesh call girl.pdfrishikeshgirls.in- Rishikesh call girl.pdf
rishikeshgirls.in- Rishikesh call girl.pdf
 
Tech Startup Growth Hacking 101 - Basics on Growth Marketing
Tech Startup Growth Hacking 101  - Basics on Growth MarketingTech Startup Growth Hacking 101  - Basics on Growth Marketing
Tech Startup Growth Hacking 101 - Basics on Growth Marketing
 
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service Jamshedpur
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service JamshedpurVIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service Jamshedpur
VIP Call Girl Jamshedpur Aashi 8250192130 Independent Escort Service Jamshedpur
 
VIP Kolkata Call Girl Howrah 👉 8250192130 Available With Room
VIP Kolkata Call Girl Howrah 👉 8250192130  Available With RoomVIP Kolkata Call Girl Howrah 👉 8250192130  Available With Room
VIP Kolkata Call Girl Howrah 👉 8250192130 Available With Room
 
2024 Numerator Consumer Study of Cannabis Usage
2024 Numerator Consumer Study of Cannabis Usage2024 Numerator Consumer Study of Cannabis Usage
2024 Numerator Consumer Study of Cannabis Usage
 
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756
Call Girls In ⇛⇛Chhatarpur⇚⇚. Brings Offer Delhi Contact Us 8377877756
 
NewBase 22 April 2024 Energy News issue - 1718 by Khaled Al Awadi (AutoRe...
NewBase  22 April  2024  Energy News issue - 1718 by Khaled Al Awadi  (AutoRe...NewBase  22 April  2024  Energy News issue - 1718 by Khaled Al Awadi  (AutoRe...
NewBase 22 April 2024 Energy News issue - 1718 by Khaled Al Awadi (AutoRe...
 
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,
BEST Call Girls In Old Faridabad ✨ 9773824855 ✨ Escorts Service In Delhi Ncr,
 
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… Abridged
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… AbridgedLean: From Theory to Practice — One City’s (and Library’s) Lean Story… Abridged
Lean: From Theory to Practice — One City’s (and Library’s) Lean Story… Abridged
 
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Mehrauli Delhi 💯Call Us 🔝8264348440🔝
 
Progress Report - Oracle Database Analyst Summit
Progress  Report - Oracle Database Analyst SummitProgress  Report - Oracle Database Analyst Summit
Progress Report - Oracle Database Analyst Summit
 
Non Text Magic Studio Magic Design for Presentations L&P.pptx
Non Text Magic Studio Magic Design for Presentations L&P.pptxNon Text Magic Studio Magic Design for Presentations L&P.pptx
Non Text Magic Studio Magic Design for Presentations L&P.pptx
 
Keppel Ltd. 1Q 2024 Business Update Presentation Slides
Keppel Ltd. 1Q 2024 Business Update  Presentation SlidesKeppel Ltd. 1Q 2024 Business Update  Presentation Slides
Keppel Ltd. 1Q 2024 Business Update Presentation Slides
 

An intro to cqrs

  • 1. DDD South West 2An Introduction to CQRS approaches to system architecture @NeilRobbins neil@computer.org
  • 2. Aims An overview of CQRS UI Command Handling View Handling How to write an Event Sourced DDD system The command handling bit
  • 3. But first some code To Visual Studio!
  • 4. What’s wrong with this? public class Event { public string Name { get; set; } public int Venue { get; set; } public DateTime Date { get; set; } public IEnumerable<Session> Sessions { get; set; } } public class Session { public PresentationPresentation { get; set; } public string Location { get; set; } public DateTime Time { get; set; } }
  • 5. But what about Queries? They’re just queries They support the UI which should provide a Decision Support System
  • 6. Intentful UI Shopping Cart Service Command Command Ratings Service Command Command Product Images Service Command Command Command Buying Choices Service Offers Service Bought Together Service
  • 7. Intentful UI Captures Intent Aligns with commands Uses the query infrastructure For display For decision support Commands should succeed Will contain logic, is typically rich
  • 8. Some Slides Big picture & background stuff!
  • 9. Façadelient Bus Commands Eventually Consistent Queries Handler
  • 10. Subscriber Subscriber Publisher Subscribers Subscriber
  • 11. ID : 123 Name : The Art of War Author: Sun Tzu ISBN: 1234ABCD5678 Event: BookIsbnChanged NewValue: 4321DCBA8765
  • 12. …there are times when we don't just want to see where we are, we also want to know how we got there http://martinfowler.com/eaaDev/EventSourcing.html
  • 13. Time to See Some Code You didn’t think I’d make you watch me type did you?
  • 14. Coding for EventSourcing namespaceProgNetDemo { public classCatalogItem { } }
  • 15. A Command Method namespaceProgNetDemo { public classCatalogItem { public void Retire() { } } }
  • 16. Some State To Change namespaceProgNetDemo { public classCatalogItem { privatebool _retired; public void Retire() { } } }
  • 17. Guard the Mutation namespaceProgNetDemo { public classCatalogItem { privatebool _retired; public void Retire() { if (!_retired) thrownewInvalidOperationException(); } } }
  • 18. Make the State Mutation A Domain Event namespaceProgNetDemo { public classCatalogItem { privatebool _retired; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } } }
  • 19. Need an Identifier for the Aggregate public classCatalogItem { privatebool _retired; privateGuid_id; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } }
  • 20. Create the Event publicclassRetiredEvent { privatereadonlyGuid _id; publicRetiredEvent(Guid id) { _id = id; } }
  • 21. Need to be Able to Apply the Event public classCatalogItem { privatebool _retired; privateGuid_id; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } }
  • 22. Create a Base Class public classAggregateRoot { protected voidApplyEvent(Event @event) { } } We’ll need to handle more than just the one type of event!
  • 23. Create the Event Type public classEvent { }
  • 24. Have our RetiredEvent Inherit From the Base Type publicclassRetiredEvent : Event { privatereadonlyGuid _id; publicRetiredEvent(Guid id) { _id = id; } }
  • 25. Still Need to Mutate the State public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } }
  • 26. Create a Method to Handle the State Change From the Event public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } private voidApplyRetiredEvent(RetiredEvent @event) { _retired = true; } }
  • 27. Done!? public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } private voidApplyRetiredEvent(RetiredEvent @event) { _retired = true; } }
  • 28. Need to Connect the Event with the Handler public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; publicCatalogItem() { RegisterHandler<RetiredEvent>(ApplyRetiredEvent); } public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } private voidApplyRetiredEvent(RetiredEvent @event) { _retired = true; } }
  • 29. Allow Handlers to be Registered public classAggregateRoot { protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { } protected voidApplyEvent(Event @event) { } }
  • 30. Create the Delegate Signature public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot { protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { } protected voidApplyEvent(Event @event) { } }
  • 31. Need to Maintain the Registry public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { var castHandler = DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); } protected voidApplyEvent(Event @event) { } }
  • 32. Delegate Adjuster:From Greg’s Blog public class DelegateAdjuster { public static Action<TBase> CastArgument<TBase, TDerived>(Expression<Action<TDerived>> source) whereTDerived : TBase { if (typeof(TDerived) ==typeof(TBase)) { return (Action<TBase>)((Delegate)source.Compile()); } ParameterExpressionsourceParameter = Expression.Parameter(typeof(TBase),"source"); varresult = Expression.Lambda<Action<TBase>>( Expression.Invoke( source, Expression.Convert(sourceParameter, typeof(TDerived))), sourceParameter); return result.Compile(); } }
  • 33. Need to Maintain the Registry public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { var castHandler = DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); _handlerRegistry.Add(typeof(TEvent), castHandler); } protected voidApplyEvent(Event @event) { } }
  • 34. Need to Apply the Event Still public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { var castHandler = DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); _handlerRegistry.Add(typeof(TEvent), castHandler); } protected voidApplyEvent(Event @event) { Action<Event> handler; if (!_handlerRegistry.TryGetValue(@event.GetType(), out handler)) { throw newInvalidOperationException(); } handler(@event); } }
  • 35. Need to Track Applied Events public delegate voidAppliesEvent<TEvent>(TEvent @event) where TEvent : Event; public classAggregateRoot { private readonlyIDictionary<Type, Action<Event>> _handlerRegistry; private readonlyICollection<Event> _events; protected voidRegisterHandler<TEvent>(AppliesEvent<TEvent> handler) whereTEvent : Event { var castHandler = DelegateAdjuster.CastArgument<Event, TEvent>(e => handler(e)); _handlerRegistry.Add(typeof(TEvent), castHandler); } protected voidApplyEvent(Event @event) { Action<Event> handler; if (!_handlerRegistry.TryGetValue(@event.GetType(), out handler)) { throw newInvalidOperationException(); } handler(@event); _events.Add(@event); } }
  • 36. All done now??? public classCatalogItem : AggregateRoot { privatebool _retired; privateGuid_id; publicCatalogItem() { RegisterHandler<RetiredEvent>(ApplyRetiredEvent); } public void Retire() { if (!_retired) thrownewInvalidOperationException(); ApplyEvent(new RetiredEvent(_id)); } private voidApplyRetiredEvent(RetiredEvent @event) { _retired = true; } } Could use a convention & just make the AggregateRoot declare which events it produces
  • 37. Not Quite Need to Expose the events for persistence & publishing Put a GetChanges() method on the AggregateRoot base class Need to be able to rebuild the Aggregate from history Put a LoadFromHistory(IEnumerable<Event> events) method on the AggregateRoot base class Reapply the events Don’t track them as changes – overload apply event protected voidApplyEvent(Event @event, booltrackAsChange) if (add) _events.Add(@event); Possibly memento pattern for snapshoting See Mark Nijhof’s blog & sample code on GitHub
  • 38. Back to the Whiteboard! Some more on Query Stores
  • 39. Some Other Benefits of Event Sourcing Already We can build new stores for new services, we have the full set of available information ready We can rebuild stores for existing services We use the same mechanism for our Query Stores as we use for any other service in the Enterprise More Granular Service Boundaries More Explicit Boundaries We aren’t just restricted to storing the Events Can send Emails based on them Can perform Complex Event Processing … The worlds your Oyster, you have the RAW MATERIAL
  • 40. Some Other Benefits of Event Sourcing Also A Very Provable Audit Log Very Simple Horizontal Scaling More Granular Service Boundaries More Explicit Boundaries Can Replay Events in Debugging Scenarios Suits Behaviour Based Testing & Outside-In Development
  • 41. NO SILVER BULLETS The coding is the EASY BIT Don’t need a grand framework The thinking & conversations is the HARD BIT
  • 42. Referenced Material/Links Greg Youngs: Course – http://bit.ly/gregscourse Blog – http://bit.ly/gregyoungsblog UdiDahans: Course – http://bit.ly/udiscourse Blog – http://bit.ly/udisblog Mark Nijhof’s sample code http://github.com/MarkNijhof/Fohjin

Editor's Notes

  1. I’m afraid my job title has the word architect in it – so we’re off to an ivory tower for this bit 
  2. Boundaries are Explicit Acknowledge potential cost (perf &amp; dev) of going between services: geographical cost trust boundaries execution environments
  3. Which might seem a strange place to begin a talk on CQRS!Every button, link the lot – is a command of interest – though not all may be handled in the same way.
  4. Which might seem a strange place to begin a talk on CQRS!Every button, link the lot – is a command of interest – though not all may be handled in the same way.
  5. Which might seem a strange place to begin a talk on CQRS!Every button, link the lot – is a command of interest – though not all may be handled in the same way.
  6. Maintaining the ViewState
  7. Capturing all state changes made to an object as Event ObjectsAdvantages:Rebuild state from eventsTemporal Queries – rebuild state to a point in timeDebugging – replay events that led to a problemSnapshotsDisadvantagesCan look a bit magical