Skip to content

Migrer vers le Event Sourcing, partie 8: supprimer la base relationnelle, devenir “Event Sourced”

by Julien on novembre 7th, 2011

An english version of this post is available here.

Vue d’ensemble

Voici maintenant la dernière étape. Après tous ces changement, il devient étonnement facile de charger les agrégats à partir de leurs événements.

Avantages

Séparation complète des responsabilités

Charger nos agrégats à partir des événements nous permet de “libérer” les tables de persistance qui font pour l’instant office de modèle d’affichage. Le modèle d’affichage peut maintenant évoluer complètement indépendamment du modèle transactionnel. Comme toujours, l’absence de couplage permet une plus grande maintenabilité. Cela devrait accélérer l’ajout de nouvelles fonctionnalités.

Mais cela veut aussi dire que la partie transactionnelle de l’application n’est plus liée à un modèle relationnel dans la base de données. Elle devient donc également plus facile à faire évoluer. D’un point de vue DDD, cela permet d’abaisser la barrière de complexité qui empêche certaines équipes de refactoriser leur modèle de domaine à chaque fois qu’elles gagnent en compréhension du domaine d’affaire, ce qui est pourtant fondamental pour espérer récolter les fruits promis par le DDD.

Implémentation

Ce qui change

Nous avons besoin de changer la façon dont nous chargeons les agrégats dans le repository:

public T ById(Guid key)
{
    var events = eventStore.LoadEventHistory(key);

    var resVal = (T)constructor.Invoke(new Object[] { events });
    AddToContext(resVal);
    return resVal;
}

Nous chargeons dans une première étape l’historique complet des événements de cet agrégat, puis appelons un nouveau constructueur qui se nourrit de ces événements.
Regardons d’abord comment les événements sont chargés:

public IEventInputStream LoadEventHistory(Guid aggregateId)
{
    using (var reader = persistenceManager.ExecuteQuery("SELECT [Version], [Data] FROM [Events] WHERE aggregate_id = @AggregateId ORDER BY [Version] ASC",
        new { AggregateId = aggregateId }))
    {
        var events = new List<IEvent>();
        var version = 0;

        while (reader.Read())
        {
            version = reader.GetInt32(0);
            var data = ((SqlDataReader)reader).GetSqlBinary(1).Value;
            events.AddRange(Deserialize(data));
        }

        return new SimpleEventInputStream(events, version, aggregateId);
    }
}

Cela consiste simplement à concaténer les événements des commits de cet agrégat.

Le nouveau constructeur de l’agrégat quant à lui appelle simplement les méthodes “Apply()” que nous avons définis dans la partie 4:

public AggregateRoot(IEventInputStream events) : this(events.AggregateId)
{
    Version = events.Version;

    foreach (var evt in events.Events)
    {
        ExecuteHandler(evt);
    }
}

private void ExecuteHandler<T>(T evt) where T : IEvent
{
    var handler = applyDelegates[this.GetType()][evt.GetType()] as Action<AggregateRoot, IEvent>;
    if (handler != null) handler(this, evt);
}

Et c’est tout. Vous avez maintenant une application CQRS / Event Sourced!

Démarrer l’application exemple

Les sources pour toute la série de billets sont disponible sur GitHub à http://github.com/jletroui/TransitioningToEventSourcing
.

Vous aurez simplement besoin de créer une base de données vide intitulée “DDDPart6″ dans SQLExpress avant de lancer l’application.
Les 3 dernières étapes de cette série étant très simples, l’exemple “partie 6″ couvre en fait les parties 6 à 8.

Liste des billets “migrer vers le Event Sourcing”:

From → Event Sourcing

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS