6. 15 – 16 November, SofiaISTACon.org
Agenda
• How it happened
• Why it happened
• How event sourcing solves the problem
• Why event sourcing benefits the company
7. 15 – 16 November, SofiaISTACon.org
Call Center Management
8. 15 – 16 November, SofiaISTACon.org
LEAD
• Id
• Name
• Email
• Phone
• Status (Available / Follow-up / Closed / Converted)
9. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status
Stefan Ivanov stefan@ivanov.com 03-27243457 Available
Viktor Kovachev viktor@kovachev.com 08-8332491 Available
Martin Mateev martin@mateev.com 04-8537112 Available
Lilyana Yankov lilyana@yankov.com 04-6092212 Available
10. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status
Stefan Ivanov stefan@ivanov.com 03-27243457 Available
Viktor Kovachev viktor@kovachev.com 08-8332491 Available
Martin Mateev martin@mateev.com 04-8537112 Available
Lilyana Yankov lilyana@yankov.com 04-6092212 Available
12. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
}
28. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
}
29. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status Follow-up
Stefan Ivanov stefan@ivanov.com 03-27243457 Available
30. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status Follow-up Date
Stefan Ivanov stefan@ivanov.com 050-8139904 Follow-up 23/11/2016
31. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status Follow-up Date
Stefan Ivanov stefan@ivanov.com 050-8139904 Converted
32. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status Follow-up Date
Stefan Ivanov stefan@ivanov.com 050-8139904 Converted
35. 15 – 16 November, SofiaISTACon.org
Changes
=
First class citizens
=
Events
36. 15 – 16 November, SofiaISTACon.org
Lead Events
• Lead Was Initialized (Id)
• Status Changed (NewStatus)
• Name Changed (NewName)
• Contact Information Changed (NewEmail, NewPhone)
• Followup Set (Date)
37. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
• Lead Was Initialized (1410)
• Status Changed (Available)
• Contact Information Changed (stefan@ivanov.com, 03-27243457)
• Status Changed (Followup)
• Followup Set (23/11/2016)
• Contact Information Changed (stefan@ivanov.com, 050-8139904)
• Status Changed (Converted)
38. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
39. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
Apply(StatusChanged event) {
this.Status = event.NewStatus;
}
40. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
Apply(NameChanged event) {
this.Name = event.NewName;
}
41. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
Apply(ContactInfoChanged event) {
this.Phone = event.NewPhone;
this.Email = event.NewEmail;
}
42. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
Apply(FollowupSet event) {
this.FollowUpOn = event.Date;
}
43. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Converted)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
44. 15 – 16 November, SofiaISTACon.org
Name Email Phone Status Follow-up Date
Stefan Ivanov stefan@ivanov.com 050-8139904 Converted
45. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Converted)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
46. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
47. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
48. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Converted)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
49. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
}
50. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Converted)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
51. 15 – 16 November, SofiaISTACon.org
public class LeadSearch {
public long Id { get; private set; }
…
public List<string> Emails;
public List<string> Phones;
…
public void Apply(ContactInfoChanged event) {…}
…
}
Apply(ContactInfoChanged event) {
this.Phones.Append(event.NewPhone);
this.Emails.Append(event.NewEmail);
}
52. 15 – 16 November, SofiaISTACon.org
public class LeadStatusChangesModel {
public long Id { get; set; }
public List<StatusLog> StatusChangesLog;
…
public void Apply(StatusChanged event) {…}
…
}
Apply(StatusChanged event) {
this.StatusChangesLog.Append(
new StatusLog(event.NewStatus,
DateTime.Now);
);
53. 15 – 16 November, SofiaISTACon.org
public class LeadStatusChangesModel {
public long Id { get; set; }
public List<StatusLog> StatusChangesLog;
…
}
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
…
}
public class LeadSearch {
public long Id { get; private set; }
public List<string> Emails;
public List<string> Phones;
…
}
54. 15 – 16 November, SofiaISTACon.org
Lead: Stefan Ivanov
Lead Was Initialized (1410)
Status Changed (Available)
Contact Information Changed (stefan@ivanov.com,03-27243457)
Status Changed (Converted)
Status Changed (Followup)
Followup Set (23/11/2016)
Contact Information Changed (stefan@ivanov.com, 050-8139904)
55. 15 – 16 November, SofiaISTACon.org
Events = Source of Truth
Event Sourcing
65. 15 – 16 November, SofiaISTACon.org
CQRS
• Command - write data
• Query - read data
• A use case can be either Command or Query. Never both
66. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Read DB
Commands
Write Model
Writes DB
Projection engine
67. 15 – 16 November, SofiaISTACon.org
Event Sourced Model (Write)
Lead #1410 1. LeadWasInitialized(1410)
2. StatusChanged(Available)
3. NameChanged(“Martin Mateev”)
4. StatusChanged(Closed)
…
1000. StatusChanged(FollowUp)
1001. FollowupSet(16/11/2017)
Read Model
Id 1410
Name Martin Mateev
Status Followup
FollowupOn (Empty)
Email …
Phone …
68. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Read DB
Commands
Write Model
Writes DB
Projection engine
69. 15 – 16 November, SofiaISTACon.org
Event Sourced Model (Write)
Lead #1410 1. LeadWasInitialized(1410)
2. StatusChanged(Available)
3. NameChanged(“Martin Mateev”)
4. StatusChanged(Closed)
5. StatusChanged(Available)
6. NameChanged(“Viktor Rumenov”)
Read Model
Id 1410
Phone …
Status Available
FollowupOn (Empty)
Email …
Name Martin Mateev
70. 15 – 16 November, SofiaISTACon.org
public class Lead {
public long Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public LeadStatus Status { get; set; }
public DateTime? FollowupOn { get; set; }
public void Apply(LeadWasInitialized event) {…}
public void Apply(StatusChanged event) {…}
public void Apply(NameChanged event) {…}
public void Apply(ContactInfoChanged event) {…}
public void Apply(FollowupSet event) {…}
}
Apply(NameChanged event) {
this.Name = event.NewName;
}
71. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Read DB
Commands
Event Sourcing
Event Store
Projection engine
72. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Read DB
Commands
Write Model
Writes DB
Projection
engine
Projection
• RDBMS
• Documents
• Graphs
• Files
73. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Commands
Write Model
Writes DB
Projection
engine
Projection
• RDBMS
• Documents
• Graphs
• Files
• Multiple DBs
Read DBs
74. 15 – 16 November, SofiaISTACon.org
Queries
Read Model
Commands
Write Model
Writes DB
Projection
engine
Read DBs
Concurrency
• Pessimistic
• Optimistic
• Optimistic on steroids
76. 15 – 16 November, SofiaISTACon.org
Event Sourcing + CQRS
• Flexible business domain modeling
• Insane scalability and availability
• Rock solid infrastructure
• …look great on your C.V.
97. 15 – 16 November, SofiaISTACon.org
€100 Discount for attendees of ISTA 2016
https://ti.to/webengineers/ddd17/discount/istacon2016
98. 15 – 16 November, SofiaISTACon.org
Domain-Driven Design
• How to identify subdomains?
• How to define business entities?
• How do define events?
• How to talk to business experts?