Subscribe to Methods & Tools

if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

**Software Development Blogs: Programming, Software Testing, Agile Project Management**

Subscribe to Methods & Tools

if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

I Could not sleepâ€¦ 3am and this ideaâ€¦

Â

Event sourcing is about **fold** but there is no
**monoid** around !

Â

Whatâ€™s a monoid ?Â

First, for those that didnâ€™t had a chance to see Cyrille Martaireâ€™sÂ fabulous explanation with beer glasses, or read the great series of post on F# for fun and profit, here is a quick recap:

Â

We need a **set**.

Letâ€™s take a simple one, positive integers.

Â

And an **operation**, let say + which takes two positive
integers.

Â

It returnsâ€¦ a positive integer. The operation is said to be **closed
on the set**.

Â

Something interesting is that 3 + 8 + 2 = 13 = (3 + 8) + 2 = 3 + (8 + 2).

This is **associativity**: (x + y) + z = x + (y + z)

Â

Le last interesting thing is 0, the **neutral element**:

x + 0 = 0 + x = x

Â

(N,+,0) is a **monoid**.

Â

Let say it again:

(S, *, Ã¸) is a monoid if

- * is closed on SÂ (* : S â€“> S > S)
- * is associative ( (x * y) * z = x * (y * z) )
- Ã¸ is the neutral element of * ( x * Ã¸ = Ã¸ * x = x )

*warning: it doesnâ€™t need to be commutative so x * y can be different
from y * x !*

Â

Some famous monoids:

(int, +, 0)

(int, *, 1)

(lists, concat, empty list)

(strings, concat, empty string)

â€¦

Â

The link with Event SourcingÂ

Event sourcing is based on an application function apply : State â€“> Event â€“> State, which returns the new state based on previous state and an event.

Â

Current state is then:

fold apply emptyState events

Â

(for those using C# Linq, fold is the same as .Aggregate)

Â

Which is great because higher level functions and allâ€¦

Â

But fold is event more powerful with monoids ! For integers, fold is called sum, and the cool thing is that itâ€™s associative !

Â

With a monoid you can fold subsets, then combine them together after (still in the right order). This is what give the full power of map reduce: move code to the data. Combine in place, then combine results. As long as you have monoids, it works.

Â

But apply will not be part of a monoid. Itâ€™s not closed on a set.

Â

To make it closed on a set it should have the following signature:

Â

apply: State â€“> State â€“> State, so we should maybe rename the function combine.

Â

Letâ€™s dreamÂ

Letâ€™s imagine we have a combine operation closed on State.

Â

Now, event sourcing goes from:

Â

decide: Command â€“> State â€“> Event list

apply: State â€“> Event â€“> State

Â

to:

decide: Command â€“> State â€“> Event list

convert: Event â€“> State

combine: State â€“> State â€“> State

Â

the previous apply function is then just:

apply state event = combine state (convert event)

Â

and fold distribution gives:

Â

**fold apply emptyState events = fold combine emptyState (map convert
events)Â **

Â

(where map applies the convert fonction to each item of the events list, as does .Select in Linq)

Â

The great advantage here is that we map then fold which is another name for reduce !

Â

Application of events can be done in parallel by chuncks and then combined !

Â

Is it just a dream ?Â

Surely not.

Â

Most of the tricky decisions have been taken in the decide function which didnâ€™t change. The apply function usually just set state members to values present in the event, or increment/decrement values, or add items to a listâ€¦ No business decision is taken in the apply function, and most of the primitive types in state members are already monoids under there usual operationsâ€¦

Â

And a group (tuple, list..) of monoid is also a monoid under a simple composition:

if (N1,*,n1) and (N2,Â¤,n2) are monoids then N1 * N2 is a monoid with an operator <*> ( (x1,x2) <*> (y1,y2) = (x1*y1, x2Â¤y2)) and a neutral element (n1,n2)â€¦

Â

To view it more easily, the convert fonction converts an event to a
**Delta**, a difference of the State.

Â

Those delta can then be aggregated/folded to make a bigger delta.

It can then be applied to a initial value to get the result !

Â

Â

The idea seams quite interesting and I never read anything about this.. If anyone knows prior study of the subject, Iâ€™m interested.

Â

Next time weâ€™ll see how to make monoids for some common patterns we can find in the apply function, to use them in the convert function.

Categories: Architecture, Requirements

Categories: Architecture, Requirements