Tag / eventsourcing

If you had any exposure to the basics of functional programming before you will at once see folds when you look at the playback-side of the event-sourcing pattern. In this post I will explore this idea a bit.

being basic

Let’s think about what the most basic event-recorder should do for us on the playback side.

Obvious it should play back the events. But what does that mean? Well on first approximation you could say it should give you a list or a sequence (or whatever) of all the events it recorded.

remark

Aside from the record side I will ignore here all the aggregate/event-ID, metadata and event-version stuff around event-sourcing. You can always add it!

For example you can add a Event-Store abstraction. You than ask this store to give you back a playback for a given aggregate-ID in a given event-version range and you are right back in our discussion.

Of course our playback should be type-safe and only return events of a given type, so the first draft for an interface could look like this:

type IPlayback<'ev> =
abstract Playback : unit -> 'ev seq

Now this perfectly fine. Yeah it’s surely not pure (well you could add a real-world parameter or wrap it into a monad if you like) but I think our stores will never be – so let’s forget about this at the moment.

What I don’t like to much is that it forces the sequence on us – let’s abstract it away.

abstracting on need

Now a sequence is one of the most basic collection you can have and I don’t want to abstract the collection – I want to abstract based on the things we are going to do with the events once we got them.

Let’s think about this a bit.

When you look at the use cases you will always end up aggregating the events in some way. You might look for a certain event, sum up values or whatever. If you saw examples in modern C# then chances are high that you used some kind of LINQ query or operators (extension methods to IEnumerable<T>) to do it – if not then there will surely be a for/foreach loop around.

The idea is this: if you loop over the events anyway than why repeat this stuff every time? Just let the playback do this for us. We just have to find the common pattern.

folding

I’ll assume that you never heard of folds (other names might be aggregate, reduce, catamorphisms, …) before and I’ll try to give you the idea here. If you are comfortable with this just skip this section.

It’s easier to see if we are using Lists, so let’s look at a few patterns:

Now we can already see some kind of pattern: the same match is everywhere. The empty case always returns some value and the non-empty cases seem all to be connected too somehow. Let’s refactor the last a bit:

Ok seems we are always using the recursive all somewhere (the last example might give you some doubt: obvious this is now worse than before – but let’s not concentrate on performance for now). Let’s see what we can do with the last part – can we abstract this somehow?

wait … this should be a Functor

If you use this for a while you will probably see that you tend to map the final result with another function (let’s call it projection) – especially if you had complicated inner states threaded through (you will see this below with the visited projection for a cargo).
And of course it would really be nice if we could make a Projection into a Functor. Well if you take a high-level peek at a Projection<'ev, 'out> you might see that this is move or less something like a mapping from a collection of events to an output-value. And of course we already know how to make something like Func<'ev seq, 'out> into a functor – we just have to compose the outcome:

Of course a IPlayback implementation now has to handle the final projection as well (just as we had to do ourselves before).
Now we can just use the projection component just as we did the arrow above and introduce a functor-map (let’s just call it map):

By the way the latest operation suggest that the order in which the IPlayback should present the events to a projections fold should be from new to old (like [5;4;3;2;1]). This works nicely if you simulate an such things with an list, because recording of an event is just the cons operation.

an example

I first came upon event-sourcing in this article: Event Sourcing by Martin Fowler, so let’s just go with his example of tracking ships.

This keeps book of the set of visited ports and the ship the cargo is on (or None if it is currently unloaded) and finally returns just the visited ports.
With this it’s easy to see if a cargo has visited a country – just use Sets exit function:

Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.

You can adjust all of your cookie settings by navigating the tabs on the left hand side.

Strictly Necessary Cookies

Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.

disable

If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.