Segregating Commands and Queries Slides
Segregating Commands and Queries Slides
Vladimir Khorikov
@vkhorikov www.enterprisecraftsmanship.com
Agenda
Scalability
Explicit
Task-based
commands Performance
interface
and queries
Simplicity
Commands in CQS vs. Commands in CQRS
EditPersonalInfo
command
StudentController
EditPersonalInfo
command handler
[HttpPut("{id}")]
public IActionResult EditPersonalInfo(long id, [FromBody] StudentPersonalInfoDto dto)
{
var command = new EditPersonalInfoCommand
{
Email = dto.Email,
Name = dto.Name,
Id = id
};
var handler = new EditPersonalInfoCommandHandler(_unitOfWork);
Result result = handler.Handle(command);
Command
Command is a
serializable method call
if (student == null)
return Result.Fail($"No student found for Id {command.Id}");
student.Name = command.Name;
student.Email = command.Email;
_unitOfWork.Commit();
return Result.Ok();
}
}
Commands and Queries in CQRS
Messages
External
applications
Events
Application
Commands Queries
Client
Naming Guidelines
EditPersonalInfo PersonalInfo
GetListQuery
Command ChangedEvent
Naming Guidelines
CreateStudentCommand
CRUD-
UpdateStudentCommand based
thinking
DeleteStudentCommand
Naming Guidelines
EditPersonalInfoCommand
GetListQuery
PersonalInfoChangedEvent
Repositories Non-core
Impure Domain domain
Services
Application
Services
Non-
UI domain
Commands and Queries in the Onion Architecture
Command = An operation to do
Commands
Trigger reaction
Push model
Pull model
Commands and Queries in the Onion Architecture
Entities
Aggregates
Value Objects Should be isolated
Domain Events from the outside world
Pure Domain
Services
Repositories
Impure Domain
Services
Application
Services Command handlers
UI go here
Commands vs. DTOs
[HttpPut("{id}")]
public IActionResult EditPersonalInfo(long id, [FromBody] StudentPersonalInfoDto dto) {
var command = new EditPersonalInfoCommand {
Email = dto.Email, Name = dto.Name, Id = id
};
var handler = new EditPersonalInfoCommandHandler(_unitOfWork);
Result result = handler.Handle(command);
[HttpPut("{id}")]
public IActionResult EditPersonalInfo( [FromBody] EditPersonalInfoCommand command) {
var handler = new EditPersonalInfoCommandHandler(_unitOfWork);
Result result = handler.Handle(command);
Commands DTOs
Serializable
Data contracts
method calls
Backward
compatibility
Commands vs. DTOs
Commands DTOs
Mapping
Backward compatible
Easy to refactor
Commands vs. DTOs
Hinder refactoring
Commands vs. DTOs
Backward
DTOs = compatibility
Actions upon
Commands = the application
Commands vs. DTOs
[HttpPut("{id}")]
public IActionResult EditPersonalInfo(
long id, [FromBody] StudentPersonalInfoDto dto)
{
var command = new EditPersonalInfoCommand(id, dto.Email, dto.Name);
Result result = _messages.Dispatch(command);
return FromResult(result);
}
return result;
}
}
Recap: Introducing Commands and Queries
services.AddSingleton(new SessionFactory(Configuration["ConnectionString"]));
services.AddTransient<UnitOfWork>();
services.AddTransient<ICommandHandler<EditPersonalInfoCommand>, EditPersonalInfoCommandHandler>();
services.AddTransient<ICommandHandler<RegisterCommand>, RegisterCommandHandler>();
services.AddTransient<ICommandHandler<UnregisterCommand>, UnregisterCommandHandler>();
services.AddTransient<ICommandHandler<EnrollCommand>, EnrollCommandHandler>();
services.AddTransient<ICommandHandler<TransferCommand>, TransferCommandHandler>();
services.AddTransient<ICommandHandler<DisenrollCommand>, DisenrollCommandHandler>();
services.AddTransient<IQueryHandler<GetListQuery, List<StudentDto>>, GetListQueryHandler>();
services.AddSingleton<Messages>();
}
Recap: Introducing Commands and Queries
public interface ICommand public interface IQuery<TResult>
{ {
} }
Success of failure
public sealed class GetListQuery :
IQuery<List<StudentDto>>
{
/* ... */
}
Recap: Introducing Commands and Queries
Commands vs DTOs
- DTOs help achieve backward
compatibility
- Commands explicitly state what the
application can do
In the Next Module