Eventos de Domínio – Geração


Os eventos de domínio nos permite identificar ações importantes que ocorrem em nossa aplicação e que desejamos divulga-la para os interessados. Por interessados, leia-se outras aplicações ou, principalmente, outros contextos que estão interligados e que reagem aos eventos para realizar uma outra atividade relacionada aquela que acabou de acontecer. Para um exemplo simples, considere uma conta corrente que ao atingir o valor negativo, a central de risco do banco deve ser acionada para entender o que está havendo com o cliente e, eventualmente, monitorar as suas atividades financeiras para evitar um prejuízo maior.

O lançamento de débito ou crédito se dá na conta corrente, e se a regra de monitoramento for atendida, temos que passar a monitorar o respectivo cliente. Incorporar eventos à classe correspondente, que neste caso é a classe que representa a conta corrente, ajudará em uma centralização de código, fácil manutenção e, principalmente, agregando à ela a responsabilidade de notificar que o saldo foi alterado (para cima ou para baixo). Competirá aos consumidores a usar a informação de acordo com a sua necessidade. O monitor de risco talvez não esteja interessado em uma conta que ficou “menos negativa”.

public class ContaCorrente
{
    //Outros membros ocultados

    public void Lancar(Lancamento lancamento)
    {
        var saldoAnterior = this.Saldo;

        this.lancamentos.Add(lancamento);
        this.Saldo += lancamento.Valor;
    }
}

Por agora, tudo o que o método acima faz é alteração da propriedade que armazena o saldo e inclui um novo lançamento na coleção interna. Depois do saldo alterado, chega o momento da conta corrente gerar o evento para notificar a alteração no saldo. A implementação padrão de eventos de domínio consiste na criação de uma marker interface, que geralmente não possui nenhum membro. Ao contrário do que acontece no .NET, onde os eventos são representados por delegates, no domínio utilizamos simples classes que implementam esta interface:

public interface IDomainEvent { }

A nomenclatura destas classes são sempre definidas no passado, que indicará que algo já ocorreu, por exemplo: NovoPedidoAdicionado, NotaFiscalEmitida, e para o nosso exemplo, SaldoDaContaAlterado. Vale lembrar que a nomenclatura deve expressar, e muito, exatamente o que ocorreu. E como já era de se esperar, todas as classes que representam eventos devem implementar a interface IDomainEvent que será útil para garantirmos a construção e uso dos tipos que envolvem a infraestrutura de eventos:

public class SaldoDaContaAlterado : IDomainEvent
{
    public SaldoDaContaAlterado(
        string nomeDoCliente, decimal saldoAnterior, decimal saldoAtual)
    {
        this.NomeDoCliente = nomeDoCliente;
        this.SaldoAnterior = saldoAnterior;
        this.SaldoAtual = saldoAtual;
    }

    public string NomeDoCliente { get; private set; }

    public decimal SaldoAnterior { get; private set; }

    public decimal SaldoAtual { get; private set; }
}

É importante notarmos que a classe que representa o evento possui algumas propriedades para descrever o que ocorreu, mas sempre temos que nos atentar em o que colocar ali, tentando manter a regra do mínimo possível necessário. Seguem algumas considerações importantes que devemos ter em mente durante a construção destas classes:

  • Entidades: é tentador colocar nestas propriedades a própria entidade que sofreu a alteração (ContaCorrente). Devemos ao máximo evitar isso, pois causará uma dependência destas classes para os interessados ao evento. Muitas vezes os eventos serão utilizados para comunicação entre contextos, e isso evitará a necessidade de referenciar a entidade (física e virtualmente). Tente optar sempre por tipos primitivos.
  • Imutabilidade: essas classes não devem ter qualquer funcionalidade (métodos), apenas os dados que correspondem ao evento gerado. As propriedades são de somente leitura e são abastecidas no construtor.
  • Ids: o Id da entidade pode ser definido no evento, mas isso só faz sentido se o consumidor já estiver colaborando com o gerador e tiver condições de recarregar a entidade, ou seja, ter acesso ao mesmo repositório. Caso o acesso não seja possível, teremos que incorporar na classe todas as informações necessárias para reportar a alteração, nem que seja necessário a duplicação de todas as informações da entidade.

Uma vez que os eventos já estão definidos, chega o momento de disparar. Como mencionado acima, o responsável pelo disparo será a própria classe que identifica a mudança, e que neste caso é a ContaCorrente, e sem qualquer análise de outra condição, dispara o evento informando que o saldo foi alterado. Note que ela irá recorrer à classe estática chamada de DomainEvents.

public class ContaCorrente
{
    //Outros membros ocultados

    public void Lancar(Lancamento lancamento)
    {
        var saldoAnterior = this.Saldo;

        this.lancamentos.Add(lancamento);
        this.Saldo += lancamento.Valor;

        DomainEvents.Raise(
            new SaldoDaContaAlterado(this.NomeDoCliente, saldoAnterior, this.Saldo));
    }
}

Agora é de responsabilidade da classe DomainEvents encontrar os consumidores deste tipo de evento e notifica-los da alteração. Há diversas técnicas que podemos utilizar na implementação da classe DomainEvents bem como em seus consumidores, mas que merece um artigo específico, e será abordado na sequência desta série.

Publicidade

3 comentários sobre “Eventos de Domínio – Geração

  1. Pingback: Eventos de Domínio – Disparo e Consumo | Israel Aece
  2. Pingback: Eventos de Domínio – Outra Opção de Disparo | Israel Aece

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s