Pergunta

Assumindo o problema do domínio da pilha e a seguinte definição de eventos:

UserRegistered(UserId, Name, Email)
UserNameChanged(UserId, Name)
QuestionAsked(UserId, QuestionId, Title, Question)

Assumindo o seguinte armazenamento de estado de eventos (na ordem da aparência):

1) UserRegistered(1, "John", "john@gmail.com")
2) UserNameChanged(1, "SuperJohn")
3) UserNameChanged(1, "John007")
4) QuestionAsked(1, 1, "Help!", "Please!")

Supondo que o seguinte modelo de leitura desnormalizado para a lista de perguntas (para a primeira página do SO):

QuestionItem(UserId, QuestionId, QuestionTitle, Question, UserName)

E o seguinte manipulador de eventos (que constrói um modelo de leitura desnormalizado):

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 
            ??? /* how should i get name of the user? */);
        ...
    }
}

Minha pergunta é Como posso encontrar o nome do usuário Quem fez uma pergunta? Ou mais comum: como devo lidar com eventos se meu modelo de leitura desnormalizado exigir dados adicionais que não existam no evento específico?

Eu examinei amostras existentes de CQRs, incluindo Simpleqrs de Greg Young e Fohjin Amostra de Mark Nijhof. Mas parece -me que eles operam apenas com dados incluídos nos eventos.

Foi útil?

Solução

Basta enriquecer o evento com todas as informações necessárias.

A abordagem de Greg, pelo que me lembro - enriquece o evento enquanto cria e armazena/publique dessa maneira.

Outras dicas

Pessoalmente, acho que não há nada de errado em procurar o nome do usuário dentro do manipulador de eventos. Mas se você estiver em uma posição em que não puder consultar o nome do modelo de leitura do usuário, apresentaria um manipulador de eventos adicional ao QuestionEventshandler, para lidar com o evento registrado pelo usuário.

Dessa forma, o questionário pode manter seu próprio repositório de nomes de usuário (você não precisaria armazenar o email dos usuários). O manipulador Questionasked pode então consultar o nome do usuário direto do seu próprio repositório (como Rinat Abdullin disse que o armazenamento é barato!).

Além disso, como o seu modelo de leitura do seu questionamento contém o nome do usuário, você precisaria lidar com o evento UsernameChanged no questionEventshandler para garantir que o campo de nome no questionamento esteja atualizado.

Para mim, isso parece menos esforço do que 'enriquecer os eventos' e tem o benefício de não Construindo dependências de outras partes do sistema e seus modelos de leitura.

Puxe os eventos do EventStore.

Lembre -se - seus modelos de leitura precisam ter acesso somente leitura à EventStore. Os modelos de leitura são descartáveis. Eles são simplesmente vistas em cache. Você poderá excluir / expirar seus modelos de leitura a qualquer momento - e reconstruir automaticamente seus READModels da EventStore. Então - seus construtores de leitores de readmodel já devem poder consultar eventos anteriores.

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        // Get Name of User
        var nameChangedEvent = eventRepository.GetLastEventByAggregateId<UserNameChanged>(question.UserId);

        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 

            nameChangedEvent.Name
    }
}

Realize também - o repositório do EventStore não precisa ser a verdadeira pista de eventos, embora certamente possa ser. A vantagem dos sistemas distribuídos é que você pode replicar facilmente o Eventstore, se necessário, mais próximo dos seus modelos.

Encontrei exatamente esse mesmo cenário ... onde eu precisava de mais dados do que estava disponível em um único evento. Isso é especialmente verdadeiro para eventos do tipo Create que exigem preencher um novo readmodelo com o estado inicial.

A partir de modelos de leitura: você pode extrair de outros modelos de leitura. Mas eu realmente não recomendo isso, pois você introduzia uma grande bola de lama de dependência, onde as visões dependem das visões dependem de visualizações.

Dados adicionais em eventos: você realmente não deseja inchar seus eventos com todos os dados extras necessários para as visualizações. Isso realmente o machucará quando seu domínio mudar e você precisar migrar eventos. Os eventos de domínio têm propósitos específicos - eles representam mudanças de estado. Não visualizar dados.

Espero que isto ajude -

Ryan

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top