Functional Domain Driven Design and Event Sourcing example in C#

Event Sourcing

This is an example of an aggregate written in C# following a functional approach similar to what it is possible to achieve with languages like F#, Scala or Clojure.

What it IS NOT in the Domain code example:

  • An AggregateBase class
  • An Aggregate Stateful class

What it IS in the Domain code example:

  • An Aggregate with some functions that take a command as an input and return correlated events

You can see the codebase here https://github.com/riccardone/EventSourcingBasket

Current State is a Left Fold of previous behaviours

Using a ‘pure’ functional language you probably follow the simplest possible way that is

f(history, command) -> events
(where history is the series of past events for a single Aggregate instance)

C# example from the Basket Aggregate Root

public static List Buy(List history, AddProduct cmd)
 {
     // Some validation and some logic
     history.Add(new ProductAdded(Guid.NewGuid().ToString(), cmd.Id, cmd.CorrelationId, cmd.Name, cmd.Cost));
     return history;
 }

Outside the domain, you can then save the events using a Repository composing the left fold of previous behaviours

yourRepository.Save(Basket.CheckOut(Basket.Buy(Basket.Create(cmd1), cmd2), cmd3));

CausationId and CorrelationId and the current state of an Aggregate Root

The CorrelationId is used to related events together in the same conversation. The CausationId is the way to know which command caused that event. The same CorrelationId is shared across all the correlated events. In a conversation, events can share a command Id as CausationId or different events can have different commands Ids depending on the execution flow. CorrelationId and CausationId can become an integral part of a Domain Event beside the unique EventId.

CausationId And CorrelationId example

CausationId And CorrelationId example

Leave a Reply

Your email address will not be published. Required fields are marked *