4lessandrodev / rich-domain

A lib to help you create a robust project based on domain driven-design (ddd) principles with typescript and zero dependencies.
https://www.npmjs.com/package/rich-domain
MIT License
122 stars 5 forks source link

Domain Events Manager Lifecycle #47

Closed hikinine closed 1 year ago

hikinine commented 1 year ago

Saudações,

A abordagem da biblioteca está excelente, zero dependências, com recursos o suficiente para modelar um domínio com um padrão coerente. As explicações no youtube também estão bacanas. Alguns dos patterns não costumo usar mas não vem ao caso.

Estou trabalhando em um fork pessoal e notei algumas possíveis situações, em especial na classe DomainEvents (lib/core/events.ts);

Imaginando um cenário em que ao criar um usuário seja registrado um evento, a instância do agregado irá registrar esse evento ao DomainEvents(Manager) que por sua vez aguardará a infra fazer o dispatch (ou não).

interface UserProps extends BaseProps {
  name: string
  age: number
}

class User extends Aggregate<UserProps>{
  private constructor(props: UserProps) {
    super(props);
  }

  static mockCreate() {
    const userProps = { name: "hikinine", age: 20 }
    const user = new User(userProps);

    if (user.isNew()) {
      user.addEvent(new UserCreatedEvent())
    }

    return user;
  }
}

export class UserCreatedEvent implements IHandle<any> {
  dispatch() {
    //...
  }
}

Assumindo um cenário em que por qualquer "X" motivo na camada de aplicação, após criar uma instancia do agregado User, ele falhe em ser persistido (ou qualquer outro cenário que interrompa o fluxo), o DomainEvent(Manager) continuará contendo o registro desse evento enquanto a aplicação não desligar.

Claro, eu posso na minha camada de infraestrutura ou até mesmo na application verificar se houve alguma falha e consequentemente utilizar o método deleteEvent. A dúvida é: existe alguma forma menos verbosa de fazer isso?

Pensei em criar uma espécie de rotina dentro da DomainEvent(Manager) verificando o createdAt, fazendo com que eventos que não receberam dispatch dentro de um intervalo de tempo pre estabelecido se auto remova, mas não me parece ideal também.

Alguma sugestão?

4lessandrodev commented 1 year ago

Olá @hikinine valeu por acompanhar meu trabalho,

Você fez uma ótima observação que eu ainda não tinha pensado sobre...

Consigo pensar em várias maneiras de solucionar isso, mas acredito que a melhor seria delegar a exclusão do evento para o próprio NODEJS ou melhor dizendo para o garbage collector, com poucas mudanças é possível armazenar os eventos no estado do próprio agregado ao invés de usar uma classe global de eventos, visto que o garbage collector não limpa referências globais que é o caso da classe DomainEvents, assim poderia sempre ao criar um agregado, iniciar uma store para eventos direto no estado do agregado que irá administrar os seus próprios eventos, assim se algum erro ocorrer a referência do agregado na memória não será mais utilizada e o próprio garbage collector se encarregará de fazer a limpeza de memória.

Ponto fraco dessa abordagem é que só seria possível disparar um evento através da instância do agregado, diferente de como está atualmente onde é possível disparar um evento para qualquer agregado através do método DomainEvents.dispatch onde é possível disparar um evento para qualquer agregado, no entando isso não seria problema de acordo com a abordagem de ddd , pois cada bounded context só possui um único agregado.

Caso isso que eu disse dê algum insight para algo diferente fique a vontade para comentar e chegarmos em uma solução.

Obrigado

hikinine commented 1 year ago

Acredito que trazer os eventos pro próprio estado do agregado seja uma excelente solução. No meu caso pelo menos não consigo enxergar um cenário onde eu precise de acesso ao evento de forma global. Vou tentar realizar um esboço essa semana.

Obrigado pelo retorno