1. Contexto de Design Orientado a Domínios (DDD)

Em DDD (Domain-Driven Design), um Aggregate (Agregado) é um padrão que ajuda a manter a integridade dos dados e a consistência dentro de um modelo de domínio. Um agregado é composto por uma raiz de agregado e uma coleção de entidades e objetos de valor que estão relacionadas entre si. A raiz de agregado é a única entrada para manipulação e acesso aos dados dentro do agregado, garantindo que todas as regras de consistência e integridade sejam aplicadas.

2. Código: Manipulação de Convite em um Evento

Código Original

No código original, a manipulação do convite é feita diretamente por meio de consultas ao banco de dados, buscando o convite específico sem considerar o agregado. Veja o trecho original:

var invitation = await _invitationRepository.GetByIdAsync(request.InvitationId, cancellationToken);

Aqui, o convite é acessado diretamente pela sua identidade, o que pode violar a integridade do modelo de domínio, especialmente se a lógica de manipulação de convites estiver encapsulada no agregado do evento (Gathering).

Mudança no Código

A mudança realizada implica que agora o convite é acessado através da raiz do agregado, que é o Gathering. Veja a alteração no código:

var gathering = await _gatheringRepository.GetByIdWithCreatorAsync(request.GatheringId, cancellationToken);
var invitation = gathering.Invitation.FirstOrDefault(i => i.Id == request.InvitationId);

Essa abordagem segue o padrão de design de agregados, onde a raiz do agregado (Gathering) é responsável por gerenciar todas as entidades e objetos de valor relacionados, como Invitation e Attendee.

3. Benefícios da Mudança

  • Consistência do Modelo de Domínio: Ao acessar o convite através da raiz do agregado, garantimos que todas as regras de negócios e a integridade dos dados são mantidas de acordo com as regras definidas na classe Gathering.

  • Encapsulamento: A lógica de aceitação do convite agora está encapsulada na classe Gathering, o que ajuda a manter o código limpo e a centralizar a lógica de manipulação de convites e participantes.

  • Simplificação do Código: A mudança reduz a necessidade de consultar diretamente o repositório de convites e integra a manipulação diretamente na lógica do agregado, facilitando a manutenção e a compreensão do código.

4. Exemplo de Implementação: Classe Gathering

Aqui está uma visão geral da classe Gathering, que é a raiz do agregado:

public sealed class Gathering : AggregateRoot
{
    private readonly List<Invitation> _invitations = new();
    private readonly List<Attendee> _attendees = new();
 
    public Member Creator { get; private set; }
    public GatheringType Type { get; private set; }
    public string Name { get; private set; }
    public DateTime ScheduledAtUtc { get; private set; }
    public string? Location { get; private set; }
    public int? MaximumNumberOfAttendees { get; private set; }
    public DateTime? InvitationsExpireAtUtc { get; private set; }
    public int NumberOfAttendees { get; private set; }
 
    public IReadOnlyCollection<Attendee> Attendees => _attendees;
    public IReadOnlyCollection<Invitation> Invitations => _invitations;
 
    public Attendee? AcceptInvitation(Invitation invitation)
    {
        // Lógica para aceitar um convite e adicionar um participante
    }
}

5. Conclusão

A mudança para acessar o convite através do agregado Gathering é uma prática recomendada em DDD. Ela assegura que todas as operações e regras de negócios associadas ao convite e aos participantes sejam gerenciadas de forma consistente e centralizada, refletindo melhor a lógica do domínio e mantendo a integridade dos dados.