implementing-decorators-upon-command-and-query-handlers-slides
implementing-decorators-upon-command-and-query-handlers-slides
Vladimir Khorikov
@vkhorikov www.enterprisecraftsmanship.com
Agenda
Enrichment
Commands
of the
and handlers
handlers
New Requirement
Database retry
Decorator Pattern
return result;
}
}
Decorator Pattern
Startup.cs
services.AddTransient<ICommandHandler<EditPersonalInfoCommand>>(provider =>
new DatabaseRetryDecorator<EditPersonalInfoCommand>(
new EditPersonalInfoCommandHandler(provider.GetService<SessionFactory>()),
provider.GetService<Config>()));
Decorator Pattern
Decorators
Introduce cross-cutting
concerns
Technical
issues
Business use
cases
Decorators Handlers
Decorator Pattern
Pipeline
D D Rich functionality
D
H D Simple components
Recap: Streamlining the Decorator
Configuration
[DatabaseRetry]
[AuditLog]
public sealed class EditPersonalInfoCommandHandler :
ICommandHandler<EditPersonalInfoCommand>
{
}
Cohesive
Recap: Streamlining the Decorator
Configuration
[DatabaseRetry]
[AuditLog]
public sealed class EditPersonalInfoCommandHandler : Several log
ICommandHandler<EditPersonalInfoCommand> records
{
}
[AuditLog]
[DatabaseRetry]
public sealed class EditPersonalInfoCommandHandler : One log
ICommandHandler<EditPersonalInfoCommand> records
{
}
Controllers = Handlers
Decorators vs. ASP.NET Middleware
Additional control
Separation of concerns
if (context.Request.Path.Value.StartsWith("/api/students/"))
[AuditLog]
[DatabaseRetry]
internal sealed class EditPersonalInfoCommandHandler
Ubiquitous
ASP.NET-related
Decorators vs. ASP.NET Middleware
Examples
Caching : IQueryHandler
Orphaned commands
and queries
Don't reuse command
handlers.
Command and Query Handlers Best Practices
Command
External call
handler 1
Command
External call
handler 1
Command and Query Handlers Best Practices
public sealed class UnregisterCommandHandler : ICommandHandler<UnregisterCommand>
{
public Result Handle(UnregisterCommand command)
{
var unitOfWork = new UnitOfWork(_sessionFactory);
var repository = new StudentRepository(unitOfWork);
Student student = repository.GetById(command.Id);
if (student == null)
return Result.Fail($"No student found for Id {command.Id}");
repository.Delete(student);
unitOfWork.Commit();
return Result.Ok();
}
}
Misuse of commands
Command and Query Handlers Best Practices
Command
External call
handler 1
Command and Query Handlers Best Practices
Command
External call
handler 1
Domain
model
Command
External call
handler 1
Used decorators to extend command and
query handlers