Question

En supposant débordement de pile problème de domaine et la définition suivante des événements:

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

En supposant que l'état suivant du magasin d'événements (dans l'ordre d'apparition):

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

En supposant que le modèle de lecture dénormaliser suivante pour les questions liste (pour la première page de SO):

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

Et le gestionnaire d'événement suivant (qui fait fond dénormaliser modèle de lecture):

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? */);
        ...
    }
}

Ma question est Comment puis-je trouver le nom de l'utilisateur qui a posé une question? Ou plus commun: comment dois-je gérer les événements si mon modèle de lecture dénormalisé nécessite des données supplémentaires qui existe pas dans le cas particulier

?

Je l'ai examiné des échantillons existants de CQRS, y compris SimpleSQRS de Greg Young et échantillon de Fohjin de Mark Nijhof. Mais il me semble qu'ils sont fonctionnent uniquement avec des données incluses dans les événements.

Était-ce utile?

La solution

Juste enrichir l'événement avec toutes les informations nécessaires.

L'approche de Greg, je me souviens bien, -. Enrichir l'événement tout en créant et stocker / publier cette façon

Autres conseils

Personnellement, je pense qu'il est faux de rien avec la recherche du nom de l'utilisateur à partir du gestionnaire d'événements. Mais si vous êtes dans une position où vous ne pouvez pas interroger le nom du modèle de lecture de l'utilisateur alors je vous présenter un gestionnaire d'événements supplémentaire QuestionEventsHandler, pour gérer l'événement UserRegistered.

De cette façon, le QuestionEventsHandler pourrait maintenir son propre référentiel de noms d'utilisateurs (vous auriez pas besoin de stocker l'e-mail des utilisateurs). Le gestionnaire QuestionAsked peut alors interroger le nom de l'utilisateur directement à partir de son propre référentiel (comme Rinat Abdullin dit le stockage ne coûte pas cher!).

En plus depuis votre modèle lu QuestionItem détient le nom, vous devez gérer l'événement UserNameChanged de l'utilisateur dans le QuestionEventsHandler et pour assurer le champ du nom dans le QuestionItem est à jour.

Pour moi, cela semble moins d'effort que « enrichir les événements » et a l'avantage de pas dépendances de construction sur d'autres parties du système et leurs modèles de lecture.

événements Tirez du EventStore.

Rappelez-vous - Vos modèles de lecture doivent avoir un accès en lecture seule au EventStore déjà. Les modèles de lecture sont à usage unique. Ils sont simplement des vues mises en cache. Vous devriez pouvoir supprimer / expireront vos modèles Lire à tout moment - et reconstruire automatiquement vos ReadModels du EventStore. Alors -. Vos ReadModelBuilders doivent déjà être en mesure de requête pour les événements passés

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
    }
}

Aussi réaliser - le dépôt EventStore doit pas être le vrai EventStore, bien qu'il pourrait certainement être. L'avantage des systèmes distribués est que vous pouvez facilement reproduire le EventStore, si vous avez besoin, plus près de vos ReadModels.

Je rencontrais ce exactement le même scénario ... où je avais besoin de plus de données que ce qui était disponible dans un seul événement. Cela est particulièrement vrai pour les événements de type Créer qui nécessitent peuplant une nouvelle ReadModel avec l'état initial.

De modèles Lire: Vous pouvez tirer d'autres modèles Lire. Mais je ne recommande pas, comme vous le feriez introduire une grosse boule de boue de dépendance où les vues dépendent des vues dépendent de vues.

Données supplémentaires à des événements: Vous ne voulez vraiment pas faire exploser la taille des événements avec toutes les données supplémentaires que vous aurez besoin pour des vues. Il va vraiment vous faire du mal lorsque vos changements de domaine et vous devez migrer des événements. Events domaine ont des objectifs spécifiques - ils représentent les changements d'état. Non afficher les données.

Hope this helps -

Ryan

scroll top