рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ CQRS + рдЗрд╡реЗрдВрдЯ рд╕реЛрд░реНрд╕рд┐рдВрдЧ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рд╢реБрд░реВ рдХреАред рдЗрд╕ рдмрд╛рд░ рдореИрдВ рдИрдПрд╕ рдХреЛ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдФрд░ рдПрдХ рдХрд░реАрдм рд╕реЗ рджреЗрдЦрдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВред
рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЬреЛ рдореИрдВрдиреЗ рдЕрдкрдиреЗ
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреЗ рд╕рд╛рде рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛
рдерд╛, рдЗрд╡реЗрдВрдЯ рд╕реЛрд░реНрд╕рд┐рдВрдЧ рдХрд╛ рдЬрд╛рджреВ IRepository рдЕрдореВрд░реНрдд рдФрд░ рджреЛ рддрд░реАрдХреЛрдВ IRepository.Save () рдФрд░ IRepository.GetById <> () рдХреЗ рдкреАрдЫреЗ рдЫрд┐рдкрд╛ рд╣реБрдЖ рдерд╛ред
рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдореИрдВрдиреЗ
рд░рд┐рдиреИрдЯ рдЕрдмреНрджреБрд▓рд┐рди рд╕реЗ
рд▓реЛрдХрдж рдЖрдИрдбреАрдбреАрдбреА рдирдореВрдирд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рд╕реЗ рдпреВрдирд┐рдЯ рдХреЛ рдмрдЪрд╛рдиреЗ рдФрд░ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдЙрдирдХреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ, рдЕрддрд┐рд░рд┐рдХреНрдд рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рдмрд┐рдирд╛, рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реАрдзреА рдЕрдкреАрд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рджрд┐рдЦрддрд╛ рд╣реИред рдПрдкреНрд▓реАрдХреЗрд╢рди рд╕рд░реНрд╡рд┐рд╕ рдХрдорд╛рдВрдбрд╣реИрдВрдбрд▓рд░ рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИ, рд▓реЗрдХрд┐рди рдЬреЛ рдПрдХ рдпреВрдирд┐рдЯ рдХреЗ рд╕рднреА рдХрдорд╛рдВрдб рдХреЛ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдФрд░ рд╣рдордиреЗ рдЗрд╕реЗ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рд╣реИред
ApplicationService
IApplicationService рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмреЗрд╣рдж рд╕рд░рд▓ рд╣реИред
public interface IApplicationService { void Execute(ICommand cmd); }
Execute рдкрджреНрдзрддрд┐ рдореЗрдВ, рд╣рдо рдХреЛрдИ рднреА рдХрдорд╛рдВрдб рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╣рдо рдЖрд╢рд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕реЗрд╡рд╛ рдЙрдиреНрд╣реЗрдВ рд╡рд╛рдВрдЫрд┐рдд рд╣реИрдВрдбрд▓рд░ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░реЗрдЧреАред
рдЪреВрдВрдХрд┐ рд░рд┐рдирд╛рдЯ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рд╕рдореБрдЪреНрдЪрдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕реЗрд╡рд╛ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдЧреНрд░рд╛рд╣рдХрдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реЗрд╡рд╛ рд╣реИред рджрд░рдЕрд╕рд▓, рдЗрд╕рд▓рд┐рдП, рдХрд┐рд╕реА рддрд░реНрдХ рдХреЛ рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдорд╣рд╛рди рд╕рдорд╛рдзрд╛рдиред
рдПрдХреНрд╕реИрдЪреНрдпреВрдЯ рд╡рд┐рдзрд┐ рдХрдорд╛рдВрдб рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ рдЬрдм рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рдУрд╡рд░рд▓реЛрдб рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХреНрд╕рдХреНрдпреВрдЯ рд╡рд┐рдзрд┐ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рдХреНрддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд╕рднреА рддрд░реАрдХреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
public void Execute(ICommand cmd) {
рдЪрд▓рд┐рдП Create рдХрдорд╛рдВрдб - CreateCustomer рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред
[Serializable] public sealed class CreateCustomer : ICommand { public CustomerId Id { get; set; } public string Name { get; set; } public Currency Currency { get; set; } public override string ToString() { return string.Format("Create {0} named '{1}' with {2}", Id, Name, Currency); } }
рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рдЖрдкрдХреЗ рдкрд╛рд╕ UI рдФрд░ ApplicationService рдХреЗ рдмреАрдЪ рдПрдХ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Rinat рдиреЗ рдЦреБрдж рдХреЛ рд╕реАрдзреЗ рд╕реЗрд╡рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ (рдХреНрд▓рд╛рд╕ ApplicationServer рджреЗрдЦреЗрдВ) рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдорд╛рдВрдб рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реАрдорд┐рдд рдХрд░ рджрд┐рдпрд╛ред
CreateCustomer рдХрдорд╛рдВрдб Execute рдореЗрдердб рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рд╡реНрд╣реЗрди рдореЗрдердб рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
public void When(CreateCustomer c) { Update(c.Id, a => a.Create(c.Id,c.Name, c.Currency, _pricingService, DateTime.UtcNow)); }
рдЕрдкрдбреЗрдЯ рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдФрд░ рдПрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдХрд╣рддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдПрдЧреНрд░реАрдЧреЗрдЯ рдкрд░ рдХреНрд░рд┐рдПрдЯ рдореЗрдердб рдмрдирд╛рдирд╛ рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рджреВрд╕рд░реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдмрдирд╛рдирд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреНрд░рд┐рдПрдЯ рдореЗрдердб рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдереЛрдбрд╝рд╛ рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИред рд╣рдо рдПрдХ рд╕рдореБрдЪреНрдЪрдп рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рджрд┐рдЦрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рд╣рдо рд░рд╛рдЬреНрдп рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдПрдХ рд╡рд┐рдзрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдБред рдбрд┐рдЬрд╛рдЗрдирд░ рдХреЗ рд╕рд╛рде, рдпрд╣ рдирд╣реАрдВ рд╣реБрдЖ рд╣реЛрдЧрд╛ред
рдЕрдкрдбреЗрдЯ рд╡рд┐рдзрд┐ рдкрд░ рд╡рд╛рдкрд╕ рд▓реМрдЯреЗрдВ, рдЙрд╕рдХреЗ рдкрд╛рд╕ рдирд┐рдореНрди рдХрд╛рд░реНрдп рд╣реИрдВ: 1) рд╡рд░реНрддрдорд╛рди рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреЗ рд▓рд┐рдП рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рд▓реЛрдб рдХрд░реЗрдВ, 2) рдПрдХ рдПрдЧреНрд░реАрдЧреЗрдЯ рдмрдирд╛рдПрдВ рдФрд░ рд▓реЛрдб рдХреА рдЧрдИ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рд░рд╛рдЬреНрдп рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ, 3) рдПрдЧреНрд░реАрдЧреЗрдЯ рдкрд░ рдкрд╛рд░рд┐рдд рдПрдХреНрд╢рди рдПрдЧреНрдЬреАрдХреНрдпреВрдЯ рдПрдХреНрд╢рди рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ, рдФрд░ 4 рдирдИ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдпрджрд┐ рдХреЛрдИ рд╣реЛред
void Update(CustomerId id, Action<Customer> execute) {
рд░рд╛рдЬреНрдп рдХреА рд╡рд╕реВрд▓реА
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдореИрдВрдиреЗ рдЬреЛ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рдпрд╛ рдерд╛, рдЙрд╕ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрджрд┐ рдЖрдк рд╕реНрдиреИрдкрд╢реЙрдЯ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд╣реАрдВ рд╣реИ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╣рд░ рдмрд╛рд░ рд░рд╛рдЬреНрдп рдХреЛ рдЪреВрд╕рдирд╛ рдпрд╛ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд░рд┐рдирдЯ рдХреЗ рдкрд╛рд╕ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ - рд░рд╛рдЬреНрдп рдХреЗ рдкрд╛рд╕ рдЧреНрд░рд╛рд╣рдХрд╕реНрдЯреИрдЯ рдирд╛рдордХ рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рд╣реИ, рдЬреЛ рд╕рдореБрдЪреНрдЪрдп рд╕реЗ рдкреНрд░рдХреНрд╖реЗрдкрдг рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдирд┐рдХрд╛рд▓рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рдФрд░ рд▓реЛрдб рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдПрдХ рд╣реА рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рд░рд╛рдЬреНрдп рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред
рдмрджрд▓реЗ рдореЗрдВ рдЗрдХрд╛рдИ рдЧреНрд░рд╛рд╣рдХ рд╡рд╕реВрд▓реА рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп рдХреА рд╡рд╕реВрд▓реА рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред
рдореИрдВ рд╕рдВрдкреВрд░реНрдг CustomerState рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдХреЛрдб рджреЗ рджреВрдВрдЧрд╛, рдореИрдВ рдХреБрдЫ рдЬрдм рдкреНрд░рдХреНрд╖реЗрдкрдг рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╣рдЯрд╛ рджреВрдВрдЧрд╛ред
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдЙрддреНрддреАрд░реНрдг рдШрдЯрдирд╛рдУрдВ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдореНрдпреВрдЯ рд╡рд┐рдзрд┐ рд╕реЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЙрдкрдпреБрдХреНрдд рдкреНрд░рдХреНрд╖реЗрдкрдг рд╡рд┐рдзрд┐ рдореЗрдВ рдмрджрд▓ рджреЗрддреА рд╣реИред
рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рднреА рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдореЗрдВ рдПрдХ рдирд┐рдЬреА рд╕реЗрдЯрд░ рд╡рд┐рдзрд┐ рд╣реИ, рдЬреЛ рдЧрд╛рд░рдВрдЯреА рджреЗрддреА рд╣реИ рдХрд┐ рд╣рдо рдХреЗрд╡рд▓ рдЗрд╕реА рдШрдЯрдирд╛ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдХреЗ рдмрд╛рд╣рд░ рд╕реЗ рд░рд╛рдЬреНрдп рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред
рд░рд╛рдЬреНрдп рдХреЛ рдмрд╣рд╛рд▓ рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЕрдм рдЖрдк рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рд╡рд┐рдзрд┐ рдореЗрдВ рдереЛрдбрд╝рд╛ рдкреАрдЫреЗ рдЪрд▓рддреЗ рд╣реИрдВред рдЬрдм рд╕реЗ рдореИрдВрдиреЗ CreateCustomer рдХрдорд╛рдВрдб рдХреЛ рд╕рдордЭрдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛, рд╣рдо рдпреВрдирд┐рдЯ рдкрд░ рдХреНрд░рд┐рдПрдЯ рд╡рд┐рдзрд┐ рдХреЛ рднреА рджреЗрдЦреЗрдВрдЧреЗред
public void Create(CustomerId id, string name, Currency currency, IPricingService service, DateTime utc) { if (_state.Created) throw new InvalidOperationException("Customer was already created"); Apply(new CustomerCreated { Created = utc, Name = name, Id = id, Currency = currency }); var bonus = service.GetWelcomeBonus(currency); if (bonus.Amount > 0) AddPayment("Welcome bonus", bonus, utc); }
рдпрд╣ рд╣рдорд╛рд░реЗ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдирд┐рдпрдореЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рд╕реНрдерд╛рди рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрдХрд╛рдИ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдирд┐рдпрдо рд╣реИ рдХрд┐ рдЧреНрд░рд╛рд╣рдХ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рддрдХрдиреАрдХреА рд╕реАрдорд╛ рднреА рд╣реИ), рдЗрд╕рд▓рд┐рдП рдЬрдм рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рд░реНрдорд┐рдд рдЗрдХрд╛рдИ рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВред
рдпрджрд┐ рд╕рднреА рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдирд┐рдпрдо рд╕рдВрддреБрд╖реНрдЯ рд╣реИрдВ, рддреЛ рд╣рдо рдЧреНрд░рд╛рд╣рдХ рд╡рд┐рдзрд┐ рд╕реЗ рд▓рд╛рдЧреВ рдкрджреНрдзрддрд┐ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдпрд╣ рдШрдЯрдирд╛ рдХреЛ рдХреЗрд╡рд▓ рд░рд╛рдЬреНрдп рд╡рд╕реНрддреБ рдкрд░ рд▓реЗ рдЬрд╛рддреА рд╣реИ рдФрд░ рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрддреА рд╣реИред
public readonly IList<IEvent> Changes = new List<IEvent>(); readonly CustomerState _state; void Apply(IEvent e) {
рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдПрдХ рдШрдЯрдирд╛ рдПрдХ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐ рдСрдкрд░реЗрд╢рди рд╣реЛрддреА рд╣реИред рд▓реЗрдХрд┐рди рдЕрднреА рдмрдирд╛рдПрдБ рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рджреЛ рдШрдЯрдирд╛рдПрдБ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред
рдЬрдм рд╣рдо рдХрд╕реНрдЯрдорд░ рдХреНрд░рд┐рдПрдЯ рдИрд╡реЗрдВрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐ рдореЗрдВ рдкрд╛рд╕ рдХрд░ рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╡рд░реНрддрдорд╛рди рдЧреНрд░рд╛рд╣рдХ рдореЗрдВ рдПрдХ рд╕реНрд╡рд╛рдЧрдд рдпреЛрдЧреНрдп рдмреЛрдирд╕ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдирд┐рдпрдо рдпрд╣ рд╣реИ рдХрд┐ рдмреЛрдирд╕ рд░рд╛рд╢рд┐ рд╢реВрдиреНрдп рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, AddPayment рдХреБрд▓ рд╡рд┐рдзрд┐ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐рд╕реА рдЪреЗрдХ рдХреЛ рдПрдХрддреНрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ CustomerPaymentAdded рдШрдЯрдирд╛ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред
public void AddPayment(string name, CurrencyAmount amount, DateTime utc) { Apply(new CustomerPaymentAdded() { Id = _state.Id, Payment = amount, NewBalance = _state.Balance + amount, PaymentName = name, Transaction = _state.MaxTransactionId + 1, TimeUtc = utc }); }
рдЕрдм рдЖрдкрдХреЛ рдирдИ рдИрд╡реЗрдВрдЯреНрд╕ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд░реАрдб рдореЙрдбрд▓ рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдирд╛ рд╣реИред рдореБрдЭреЗ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдЧрд▓реА рдкрдВрдХреНрддрд┐ рд╣реИред
рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ ...
public void AppendToStream(IIdentity id, long originalVersion, ICollection<IEvent> events) { if (events.Count == 0) return; var name = IdentityToString(id); var data = SerializeEvent(events.ToArray()); try { _appendOnlyStore.Append(name, data, originalVersion); } catch(AppendOnlyStoreConcurrencyException e) {
рдЦреИрд░, рд▓рдЧрднрдЧ рдкреНрд░рд╕рдиреНрдиред рдШрдЯрдирд╛рдУрдВ рдХреЛ рдХреНрд░рдордмрджреНрдз рдФрд░ рдХреЗрд╡рд▓ рд╕реНрдЯреЛрд░ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛рдиреЗ рдФрд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдирд╣реАрдВ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ)ред рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рд░реАрдб-рдореЙрдбрд▓ (рдкреНрд░рд╕реНрддреБрддрд┐ рд╕реНрддрд░ рдкрд░) рдкрд░ рднреЗрдЬрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд░рд┐рдиреИрдЯ рдЙрдиреНрд╣реЗрдВ рдХреЗрд╡рд▓ рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред
рдпрджрд┐ рдЖрдк рдпрд╣ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рддреЛ рдЖрдк рдореЗрд░реЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреЗ рдЧрд┐рдардм рдкрд░
рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВрдиреЗ рдЗрд╕реЗ рдереЛрдбрд╝рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдФрд░ рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдЗрд╡реЗрдВрдЯ рд╕реЛрд░реНрд╕рд┐рдВрдЧ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рднреА рдкреЗрд╢ рдХрд┐рдпрд╛ред рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореИрдВ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреИрд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред
рд╕реНрдиреИрдкрд╢реЙрдЯреНрд╕
рдпреВрдирд┐рдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдордзреНрдпрд╡рд░реНрддреА рд╕реНрдиреИрдкрд╢реЙрдЯ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рд╣рдореЗрдВ рдпреВрдирд┐рдЯ рдХреЗ рдШрдЯрдирд╛рдУрдВ рдХреЗ рдкреВрд░реЗ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рд╕реНрдиреИрдкрд╢реЙрдЯ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж рд╣реБрдП рдереЗред
рддреЛ рдЖрдЗрдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦреЗрдВред
UserCommandHandler рд╡рд░реНрдЧ рдореЗрдВ рд░рд┐рдиреИрдЯ рдХреЗ рд╕рдорд╛рди рдПрдХ рдЕрдкрдбреЗрдЯ рд╡рд┐рдзрд┐ рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдЕрднреА рднреА рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рд╕рд╣реЗрдЬрддрд╛ рд╣реИ рдФрд░ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИред рд╣рдо рд╣рд░ 100 рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рд╕реНрдиреИрдкрд╢реЙрдЯ рдХрд░рддреЗ рд╣реИрдВред
private const int SnapshotInterval = 100;
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рднрдВрдбрд╛рд░ рд╕реЗ рдПрдХ рд╕реНрдиреИрдкрд╢реЙрдЯ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╣рдо рдЗрд╕ рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдШрдЯрдирд╛рдУрдВ рдХреА рдзрд╛рд░рд╛ рдХреЛ рд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдпреВрдирд┐рдЯ рдХреЗ рдбрд┐рдЬрд╛рдЗрдирд░ рдХреЛ рдпрд╣ рд╕рдм рджреЗрддреЗ рд╣реИрдВред
private void Update(string userId, Action<UserAR> updateAction) { var snapshot = _snapshotRepository.Load(userId); var startVersion = snapshot == null ? 0 : snapshot.StreamVersion + 1; var stream = _eventStore.OpenStream(userId, startVersion, int.MaxValue); var user = new UserAR(snapshot, stream); updateAction(user); var originalVersion = stream.GetVersion(); _eventStore.AppendToStream(userId, originalVersion, user.Changes); var newVersion = originalVersion + 1; if (newVersion % SnapshotInterval == 0) { _snapshotRepository.Save(new Snapshot(userId, newVersion,user.State)); } }
рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рд╣рдо рд╕реНрдиреИрдкрд╢реЙрдЯ рд╕реЗ рд░рд╛рдЬреНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдпрд╛ рд╕реНрдиреИрдкрд╢реЙрдЯ рди рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдкреНрд░рд╛рдкреНрдд рд╕реНрдерд┐рддрд┐ рдкрд░, рд╣рдо рд╕рднреА рд▓рд╛рдкрддрд╛ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдЦреЛ рджреЗрддреЗ рд╣реИрдВ, рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╣рдореЗрдВ рдЗрдХрд╛рдИ рдХрд╛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рдорд┐рд▓рддрд╛ рд╣реИред
public UserAR(Snapshot snapshot, TransitionStream stream) { _state = snapshot != null ? (UserState) snapshot.Payload : new UserState(); foreach (var transition in stream.Read()) { foreach (var @event in transition.Events) { _state.Mutate((IEvent) @event.Data); } } }
рд╕рдореБрдЪреНрдЪрдп рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЬрд╛рдБрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдХреБрд▓ рд╕рдВрд╕реНрдХрд░рдг рдПрдХ рдЕрдВрддрд░рд╛рд▓ рд╣реИ рдЬрд┐рд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдо рд╕реНрдиреИрдкрд╢реЙрдЯ рд▓реЗрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдРрд╕рд╛ рд╣реИ, рддреЛ рдирдП рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВред UserCommandHandler рд╕реЗ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕реНрдЯреЗрдЯ рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдЗрдВрдЯрд░рдирд▓ рдЧреЗрдЯреНрдЯрд░ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ред
рдпрд╣реА рд╕рдм рд╣реИ, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реНрдиреИрдкрд╢реЙрдЯ рд╣реИрдВ, рдЬрд┐рд╕рдиреЗ рд╣рдореЗрдВ рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдШрдЯрдирд╛рдУрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЗрдХрд╛рдИ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдмрд╣рд╛рд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА рд╣реИред
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛
рдпрджрд┐ рдЖрдк CQRS + ES рдХреЗ рд╡рд┐рд╖рдп рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдХреГрдкрдпрд╛ рдмреЗрдЭрд┐рдЭрдХ рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ рд╕рд╡рд╛рд▓ рдкреВрдЫ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рд╣рдм рдкрд░ рдХреЛрдИ рдЙрд░реНрдл тАЛтАЛрдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдореБрдЭреЗ рд╕реНрдХрд╛рдЗрдк рдкрд░ рднреА рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдЪреЗрд▓реНрдпрд╛рдмрд┐рдВрд╕реНрдХ рдХреЗ рдПрдХ рджреЛрд╕реНрдд рдиреЗ рдореЗрд░реЗ рд╕реНрдХрд╛рдЗрдк рдкрд░ рджрд╕реНрддрдХ рджреА рдФрд░ рдЙрдирдХреЗ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рдХрд╛рд░рдг рдореБрдЭреЗ рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╡рд┐рдЪрд╛рд░ рдорд┐рд▓реЗред рдЪреВрдВрдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдЕрдм рдЕрдкрдиреЗ рдирд┐рдкрдЯрд╛рди рдореЗрдВ рдЕрдзрд┐рдХ рдЦрд╛рд▓реА рд╕рдордп рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдЕрдзрд┐рдХ рдмрд╛рд░ рд▓рд┐рдЦрдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рддрд╛ рд╣реВрдВред