SlideShare a Scribd company logo
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 2020
Jerry 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 Files
David 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
 
Introduction to android
Introduction to androidIntroduction to android
Introduction to android
Arbuleac Eugeniu
 
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
 
React lecture
React lectureReact lecture
React lecture
Christoffer Noring
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
Christoffer Noring
 
Android TDD
Android TDDAndroid TDD
Android TDD
Godfrey Nolan
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
Christoffer Noring
 
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy
 
Maze
MazeMaze
Maze
yito24
 
Intro to React | DreamLab Academy
Intro to React | DreamLab AcademyIntro to React | DreamLab Academy
Intro to React | DreamLab Academy
DreamLab
 
Protocol-Oriented Networking
Protocol-Oriented NetworkingProtocol-Oriented Networking
Protocol-Oriented Networking
Mostafa 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 edition
Christian 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 your life with Kafka
Event your life with KafkaEvent your life with Kafka
Event your life with Kafka
Mari Carmen Gutiérrez
 
Event-driven architecture
Event-driven architectureEvent-driven architecture
Event-driven architecture
Andrew Easter
 
Eventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDBEventsourcing with PHP and MongoDB
Eventsourcing with PHP and MongoDB
Jacopo Nardiello
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
Sébastien Houzé
 
EventSourcing applied
EventSourcing appliedEventSourcing applied
EventSourcing applied
Rickard Öberg
 
Event-sourcing avancé avec Scala
Event-sourcing avancé avec ScalaEvent-sourcing avancé avec Scala
Event-sourcing avancé avec Scala
Paris Scala User Group
 
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 sourcing
Rich Lee
 
From ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingFrom ActiveRecord to EventSourcing
From ActiveRecord to EventSourcing
Emanuele DelBono
 
TYPO3 Event Sourcing
TYPO3 Event SourcingTYPO3 Event Sourcing
TYPO3 Event Sourcing
Oliver Hader
 
DDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFrameworkDDD Framework for Java: JdonFramework
DDD Framework for Java: JdonFramework
banq 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 Microservices
Lightbend
 

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 VRaptor
Caelum
 
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
Pavel 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 InfrastructureC.T.Co
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureAlexey Buzdin
 
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
velveeta_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 Tutorial
jbarciauskas
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
Ankit 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
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
Ryunosuke SATO
 
Jersey Guice AOP
Jersey Guice AOPJersey Guice AOP
Jersey Guice AOP
Domenico Briganti
 

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

Sustainability: Balancing the Environment, Equity & Economy
Sustainability: Balancing the Environment, Equity & EconomySustainability: Balancing the Environment, Equity & Economy
Sustainability: Balancing the Environment, Equity & Economy
Operational Excellence Consulting
 
Digital Transformation and IT Strategy Toolkit and Templates
Digital Transformation and IT Strategy Toolkit and TemplatesDigital Transformation and IT Strategy Toolkit and Templates
Digital Transformation and IT Strategy Toolkit and Templates
Aurelien Domont, MBA
 
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
Lviv Startup Club
 
Kseniya Leshchenko: Shared development support service model as the way to ma...
Kseniya Leshchenko: Shared development support service model as the way to ma...Kseniya Leshchenko: Shared development support service model as the way to ma...
Kseniya Leshchenko: Shared development support service model as the way to ma...
Lviv Startup Club
 
3.0 Project 2_ Developing My Brand Identity Kit.pptx
3.0 Project 2_ Developing My Brand Identity Kit.pptx3.0 Project 2_ Developing My Brand Identity Kit.pptx
3.0 Project 2_ Developing My Brand Identity Kit.pptx
tanyjahb
 
Premium MEAN Stack Development Solutions for Modern Businesses
Premium MEAN Stack Development Solutions for Modern BusinessesPremium MEAN Stack Development Solutions for Modern Businesses
Premium MEAN Stack Development Solutions for Modern Businesses
SynapseIndia
 
Affordable Stationery Printing Services in Jaipur | Navpack n Print
Affordable Stationery Printing Services in Jaipur | Navpack n PrintAffordable Stationery Printing Services in Jaipur | Navpack n Print
Affordable Stationery Printing Services in Jaipur | Navpack n Print
Navpack & Print
 
Introduction to Amazon company 111111111111
Introduction to Amazon company 111111111111Introduction to Amazon company 111111111111
Introduction to Amazon company 111111111111
zoyaansari11365
 
The Influence of Marketing Strategy and Market Competition on Business Perfor...
The Influence of Marketing Strategy and Market Competition on Business Perfor...The Influence of Marketing Strategy and Market Competition on Business Perfor...
The Influence of Marketing Strategy and Market Competition on Business Perfor...
Adam Smith
 
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
bosssp10
 
Exploring Patterns of Connection with Social Dreaming
Exploring Patterns of Connection with Social DreamingExploring Patterns of Connection with Social Dreaming
Exploring Patterns of Connection with Social Dreaming
Nicola Wreford-Howard
 
Buy Verified PayPal Account | Buy Google 5 Star Reviews
Buy Verified PayPal Account | Buy Google 5 Star ReviewsBuy Verified PayPal Account | Buy Google 5 Star Reviews
Buy Verified PayPal Account | Buy Google 5 Star Reviews
usawebmarket
 
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
Boris Ziegler
 
In the Adani-Hindenburg case, what is SEBI investigating.pptx
In the Adani-Hindenburg case, what is SEBI investigating.pptxIn the Adani-Hindenburg case, what is SEBI investigating.pptx
In the Adani-Hindenburg case, what is SEBI investigating.pptx
Adani case
 
Company Valuation webinar series - Tuesday, 4 June 2024
Company Valuation webinar series - Tuesday, 4 June 2024Company Valuation webinar series - Tuesday, 4 June 2024
Company Valuation webinar series - Tuesday, 4 June 2024
FelixPerez547899
 
Enterprise Excellence is Inclusive Excellence.pdf
Enterprise Excellence is Inclusive Excellence.pdfEnterprise Excellence is Inclusive Excellence.pdf
Enterprise Excellence is Inclusive Excellence.pdf
KaiNexus
 
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdfBài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
daothibichhang1
 
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdfMeas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
dylandmeas
 
Putting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxPutting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptx
Cynthia Clay
 
Discover the innovative and creative projects that highlight my journey throu...
Discover the innovative and creative projects that highlight my journey throu...Discover the innovative and creative projects that highlight my journey throu...
Discover the innovative and creative projects that highlight my journey throu...
dylandmeas
 

Recently uploaded (20)

Sustainability: Balancing the Environment, Equity & Economy
Sustainability: Balancing the Environment, Equity & EconomySustainability: Balancing the Environment, Equity & Economy
Sustainability: Balancing the Environment, Equity & Economy
 
Digital Transformation and IT Strategy Toolkit and Templates
Digital Transformation and IT Strategy Toolkit and TemplatesDigital Transformation and IT Strategy Toolkit and Templates
Digital Transformation and IT Strategy Toolkit and Templates
 
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
Evgen Osmak: Methods of key project parameters estimation: from the shaman-in...
 
Kseniya Leshchenko: Shared development support service model as the way to ma...
Kseniya Leshchenko: Shared development support service model as the way to ma...Kseniya Leshchenko: Shared development support service model as the way to ma...
Kseniya Leshchenko: Shared development support service model as the way to ma...
 
3.0 Project 2_ Developing My Brand Identity Kit.pptx
3.0 Project 2_ Developing My Brand Identity Kit.pptx3.0 Project 2_ Developing My Brand Identity Kit.pptx
3.0 Project 2_ Developing My Brand Identity Kit.pptx
 
Premium MEAN Stack Development Solutions for Modern Businesses
Premium MEAN Stack Development Solutions for Modern BusinessesPremium MEAN Stack Development Solutions for Modern Businesses
Premium MEAN Stack Development Solutions for Modern Businesses
 
Affordable Stationery Printing Services in Jaipur | Navpack n Print
Affordable Stationery Printing Services in Jaipur | Navpack n PrintAffordable Stationery Printing Services in Jaipur | Navpack n Print
Affordable Stationery Printing Services in Jaipur | Navpack n Print
 
Introduction to Amazon company 111111111111
Introduction to Amazon company 111111111111Introduction to Amazon company 111111111111
Introduction to Amazon company 111111111111
 
The Influence of Marketing Strategy and Market Competition on Business Perfor...
The Influence of Marketing Strategy and Market Competition on Business Perfor...The Influence of Marketing Strategy and Market Competition on Business Perfor...
The Influence of Marketing Strategy and Market Competition on Business Perfor...
 
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
Call 8867766396 Satta Matka Dpboss Matka Guessing Satta batta Matka 420 Satta...
 
Exploring Patterns of Connection with Social Dreaming
Exploring Patterns of Connection with Social DreamingExploring Patterns of Connection with Social Dreaming
Exploring Patterns of Connection with Social Dreaming
 
Buy Verified PayPal Account | Buy Google 5 Star Reviews
Buy Verified PayPal Account | Buy Google 5 Star ReviewsBuy Verified PayPal Account | Buy Google 5 Star Reviews
Buy Verified PayPal Account | Buy Google 5 Star Reviews
 
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
Agency Managed Advisory Board As a Solution To Career Path Defining Business ...
 
In the Adani-Hindenburg case, what is SEBI investigating.pptx
In the Adani-Hindenburg case, what is SEBI investigating.pptxIn the Adani-Hindenburg case, what is SEBI investigating.pptx
In the Adani-Hindenburg case, what is SEBI investigating.pptx
 
Company Valuation webinar series - Tuesday, 4 June 2024
Company Valuation webinar series - Tuesday, 4 June 2024Company Valuation webinar series - Tuesday, 4 June 2024
Company Valuation webinar series - Tuesday, 4 June 2024
 
Enterprise Excellence is Inclusive Excellence.pdf
Enterprise Excellence is Inclusive Excellence.pdfEnterprise Excellence is Inclusive Excellence.pdf
Enterprise Excellence is Inclusive Excellence.pdf
 
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdfBài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
Bài tập - Tiếng anh 11 Global Success UNIT 1 - Bản HS.doc.pdf
 
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdfMeas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
Meas_Dylan_DMBS_PB1_2024-05XX_Revised.pdf
 
Putting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxPutting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptx
 
Discover the innovative and creative projects that highlight my journey throu...
Discover the innovative and creative projects that highlight my journey throu...Discover the innovative and creative projects that highlight my journey throu...
Discover the innovative and creative projects that highlight my journey throu...
 

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