Upload
vladik-khononov
View
4.959
Download
2
Embed Size (px)
Citation preview
Introduction to Event Sourcing
… and CQRS
Vladik KhononovChief Architect at Internovus
http://il.linkedin.com/in/vladikkhononov/
vladikk vladikkhttp://vladikk.com
Information Systems
HTML5AngularJSWPFIOSFlashExtJSAndroidSilverlightResponsive webdesignSPACSS3UserInterface
UserInterface MySQLMongoDBDynamoDBNeo4jRavenDBPostgreSQLHBaseCassandraSql ServerMariaDBRedisCouchDBData
Access
UserInterface
Data Access“Verbs & Nouns”Domain Driven
DesignBusiness
Logic
Domain Driven Design?
UserInterface
Business Logic
Data Access
– www.dictionary.com
Model: A simplified representation of a system or phenomenon.
– www.wikipedia.org
, שמטרתו: מורכבת מערכת של תאורטי ייצוג מודלמהותיים בהיבטים המערכת את המודל. לחקות
, מתייחס אלא במערכת תופעה כל מתאר אינו. שלה ומצומצמים מוגדרים מבוסס להיבטים המודל
, איחוד הפשטה של בדרך המציאות של קירוב עלאינה שהשפעתם מגורמים והתעלמות ישויות
.מהותית
UserInterface
Business Logic
Data Access
Domain Model
Good Domain Model• Not too much
• Not too less
• Sweet spot
• The information we need
• The information we will need
Why domain models fail
• We absolutely suck at predicting the future
• No single model can suit all the use cases
• Model transformations are painful
Case Study: Customers
Management
• A customer has customer id number and a name
• A customer has contact information: email, phone number
• A customer can be in on of the following states:New, CallLater, Converted, NotInterested
• A seller has seller id number, name and password
• The selling home page contains a list of the customers in the following statuses:
• New• CallLater (when scheduled call date is
met)
• Seller chooses a customer to call from the home page
• Seller can change the customer’s status to “Converted”, “Not Interested”
• Seller can schedule a future call by setting the future call date. The Customer’s status will change to “CallLater”
• Seller can change name, email, and phone number
enum Status {New, CallLater, Converted,NotInterested
}
class Customer {int Id;string Name;Status Status;DateTime? ScheduledCall;string Email;string PhoneNumber;
}
CREATE TABLE Customers (ID
INTEGER,Name
CHAR(40),Email
CHAR(40),PhoneNumber
CHAR(40),Status
INTEGER,ScheduledCall DATETIME,PRIMARY KEY (ID)
)
class Seller {int Id;string Name;string Password;
}
CREATE TABLE Sellers (ID
INTEGER,Name CHAR(40),Password CHAR(40)PRIMARY KEY (ID)
)
• Seller can find customers by name, email, and/or phone number in the search page
• The customers should be found by the current and the past values
• If no new customers are available on the home page, it should display customers in the NotInterested status, if it was set more than a 30 days ago
• Analysts should be able to review status changes history for each customer - change date and the new status
class Seller {int Id;string Name;string Password;
}
CREATE TABLE Sellers (ID
INTEGER,Name CHAR(40),Password CHAR(40)PRIMARY KEY (ID)
)
enum Status {New, CallLater, Converted,NotInterested
}
class Customer {int Id;string Name;Status Status;DateTime? ScheduledCall;string Email;string PhoneNumber;
}
CREATE TABLE Customers (ID
INTEGER,Name
CHAR(40),Email
CHAR(40),PhoneNumber
CHAR(40),Status
INTEGER,ScheduledCall DATETIME,PRIMARY KEY (ID)
)
Id Name Email Phone number Status Scheduled Call
10 John [email protected] 04-2342343 New
Id Name Email Phone number Status Scheduled Call
10 John [email protected] 04-2342343 CallLater
27/10/2014
Id Name Email Phone number Status Scheduled Call
10 John [email protected] 08-9876653 CallLater
27/10/2014
Event SourcingCapture all changes to an
application state as a sequence of events
~ Martin Fowler
class StatusChanged : IEvent {Status NewStatus;DateTime CreatedOn; int CreatedBy;
}
class FutureCallScheduled : IEvent {DateTime ScheduledCallTime;DateTime CreatedOn; int CreatedBy;
}
class ContactDetailsWereUpdated : IEvent {string NewName;string NewEmail;string NewPhone;DateTime CreatedOn; int CreatedBy;
}
class Customer {int Id;string Name;string Email;string PhoneNumber;Status Status;DateTime? ScheduledCall;List<IEvent> Events;
…
void Apply(StatusChanged e) {Status = e.NewStatus;Events.Add(e);
}….….
}
class Customer {int Id;string Name;string Email;string PhoneNumber;Status Status;DateTime? ScheduledCall;List<IEvent> Events;
……
void Apply(FutureCallScheduled e) {ScheduledCall = e.ScheduledCallTime;Events.Add(e);
}
…}
class Customer {int Id;string Name;string Email;string PhoneNumber;Status Status;DateTime? ScheduledCall;List<IEvent> Events;
………
void Apply(ContactDetailsWereUpdated e) {Name = e.NewName;Email = e.NewEmail;PhoneNumber = e.NewPhoneNumber;Events.Add(e);
}}
1. new StatusChanged(Status.CallLater)
2. new FutureCallScheduled(’27/10/2014’)
3. new ContactDetailsWereUpdated( NewPhoneNumber=’08-9876653’)
4. new StatusChanged(Status.Converted)
Event StorageEntity Id + New events
Entity IdEvent1,Event2,Event3,
….
class CustomerSearchModel {int Id;List<string> Names;List<string> Emails;List<string> PhoneNumbers;Status Status;DateTime? ScheduledCall;………
void Apply(ContactDetailsWereUpdated e) {Names.Add(e.NewName);Emails.Add(e.NewEmail);PhoneNumbers.Add(e.NewPhoneNumber);
}}
class CustomerAnalysisModel {int Id;string Name;string Email;string
PhoneNumber;List<StatusChange> StatusChanges;DateTime? ScheduledCall;
…
void Apply(StatusChanged e) {StatusChanges.Add(
new StatusChange(e.CreatedOn, e.NewStatus)
);}….….
}
class Customer {int Id;string Name;string Email;string
PhoneNumber;Status Status;DateTime?
ScheduledCall;List<IEvent> Events;
}
class CustomerSearchModel {int Id;List<string> Names;List<string> Emails;List<string> PhoneNumbers;Status Status;DateTime? ScheduledCall;
}
class CustomerAnalysisModel {int Id;string
Name;string
Email;string
PhoneNumber;List<StatusChange>
StatusChanges;DateTime?
ScheduledCall;}
Good Domain Model• Not too much
• Not too less
• Sweet spot
• The information we need
• The information we might need
Why domain models fail
• We absolutely suck at predicting the future
• No single model can suit all the use cases(e.g.: transactional processing, business intelligence, search)
• Model transformations are painful
Event StorageEntity Id + New events
Entity IdEvent1,Event2,Event3,
….
CQRSCommand Query Responsibility
Segregation
Laye
red
Arch
itect
ure
Step
1
Step
2
Step
3
CQRS
• Event based models
• Effective modeling
• No future predicting required
• Time machine
• Retroactive debugging
• Infrastructural freedom
• Infinite scalability
• Easy to scale writes
• Easy to scale reads
Conclusions
Bounded Contexts
Domain Types
• Core Domain
• Subdomain
• Generic Subdomain
Plexop
Campaign Management
(Core Domain)Creative Catalog
(Subdomain)
User Management(Generic Subdomain)
Billing(Generic Subdomain)
Before you try this at home
• Read “Implementing Domain Driven Design” by Vaughn Vernon
• Read “Domain Driven Design” by Eric Evans
• Follow Greg Young, Udi Dahan, DDD community
• Read DDD/CQRS on Google Groups
• Join http://meetup.com/DDD-IL :)
Questions?
http://il.linkedin.com/in/vladikkhononov
http://twitter.com/vladikk
http://vladikk.com