TaskHub.Shared.Domain provides the core building blocks for implementing a rich domain model using Domain-Driven Design (DDD).
An Aggregate is a cluster of domain objects that can be treated as a single unit. An Aggregate Root is the entry point to the aggregate.
All aggregate roots should inherit from this class. It provides:
public class TaskItem : AggregateBase<Guid>
{
public TaskItem(Guid id, string title) : base(id)
{
Title = title;
AddEvent(new TaskCreatedDomainEvent(id, title));
}
public string Title { get; private set; }
public TaskStatus Status { get; private set; } = TaskStatus.Pending;
public void Complete()
{
if (Status == TaskStatus.Completed) return;
Status = TaskStatus.Completed;
AddEvent(new TaskCompletedDomainEvent(Id));
}
}
Domain events represent a significant occurrence within the domain. They are handled within the same transaction as the aggregate change (unless using the Outbox pattern for integration).
Events should be immutable and implement IDomainEvent.
public record TaskCompletedDomainEvent(Guid TaskId) : DomainEventBase;
Implement IEventHandler<T> to react to events.
public class NotifyOwnerOnTaskCompleted(IEmailService emailService) : IEventHandler<TaskCompletedDomainEvent>
{
public async Task HandleAsync(TaskCompletedDomainEvent ev, CancellationToken ct)
{
// ... send email logic
}
}
Use domain-specific exceptions to capture business rule violations. This allows the application layer to distinguish between technical errors and business logic failures.
public class TaskAlreadyCompletedException() : DomainException("Task is already completed.");
private set.