FsUno.Prod


Why F# ?

tldr; I wanted to implement Functional Event Sourcing, and needed a functional language for this. F#'s DSL oriented syntax proved useful on the way.

2014-08-10

Event Sourcing

Back in 2008, this thing called event sourcing started to draw my attention as I started to feel the limits of doing Domain Driven Design using an ORM.

Discussion after discussion on the DDD yahoo group with Greg Young and others; things started to make sense. But a lot of points remained a bit fuzzy.

Taking Greg's course in Paris made all this a lot clearer, but still I was not totally comfortable with the implementation. I put a first attempt in production and it's still running, but I was not totally OK with the result.

Then I met Rinat Abdullin, and we created #cqrsbeers in Paris. Rinat had a wonderfuly efficient implementation of Event Sourcing in C# locally or on Azure open sourced from the company he was working in at that time.

It was lean and mean, very inspiring, in production; and yet it was not enough.

Functional Event Sourcing

Then at Skillsmatter's DDDx 2013, Greg did a presentation about DDD Functional Programming. I was starting to learn F# at that time, and here things matched perfectly.

Functional event sourcing is defined around two functions:

The first one is in charge of deciding what's happening:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
type Command = | DoSomething 
type Event = | SomethingHappened

let decide state command =
    match command with
    | DoSomething ->
        if state.MyCurrentState = "..." then ()
            // take some decision based on the command and
            // the current state and return events that should
            // result in this case
        [ SomethingHappened ] 

Simple enough, and with immutable values, decide is a pure function without side effects.

Its signature indicates it's meaning:

1: 
State -> Command -> Event list

can be read as given my current state and what you ask me to do, here is what happens.

This is something that had always bugged me with OO Event Sourcing; you have to be careful not to mutate your state before building your events. But nothing prevents you from doing so and shooting yourself in the foot.

Then comes the event application function.

1: 
2: 
3: 
4: 
let apply state event =
    match event with
    | SomethingHappened ->
        { state with MyCurrentState = "something derived from event content" }

Here again, a pure function without side effects.

The signature is :

1: 
State -> Event -> State

and can be read as given my current state and what happened, here is my new state

No risk of corruption of internal state if something bad happens during processing; all is immutable.

And rebuilding the current state is as easy as

1: 
let replay events = List.fold apply State.empty events

F#

So I started to try implementing Greg's SimpleCQRS sample in F# and could see that much of the pain went away, even if I was still a noob in F#.

A central aspect of F# is that it has a type system that eerily seems almost purpose-built for DDD. Have a look at Scott Wlaschin's presentation on DDD with F# and the associated series on his blog.

Another one is that F# has immutable and Non Null types by default.

It also has a DSLly feeling due to the low noise -- no curlies - and currying.

It's also a language that can be put into production on many platforms thanks to Xamarin.

All this combined together makes it a good way to implement Event Sourcing. It's robust, clean and fast. It's also a great way to teach Event Sourcing, even to people who don't speak F#.

I've done several presentations in F# in front of Java people - "You don't talk C# and I don't talk Java, let's do this in F# !" - and it was totally ok.

This being said, most of the things here can be applied outside of F# with possibly minor adjustments. If you find any, let's chat, and I can talk about it here.

State.MyCurrentState: string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
static member State.empty : State

Full name: Why FSharp.State.empty
type Command = | DoSomething

Full name: Why FSharp.Command
union case Command.DoSomething: Command
Multiple items
module Event

from Microsoft.FSharp.Control

--------------------
type Event = | SomethingHappened

Full name: Why FSharp.Event

--------------------
type Event<'T> =
  new : unit -> Event<'T>
  member Trigger : arg:'T -> unit
  member Publish : IEvent<'T>

Full name: Microsoft.FSharp.Control.Event<_>

--------------------
type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
  new : unit -> Event<'Delegate,'Args>
  member Trigger : sender:obj * args:'Args -> unit
  member Publish : IEvent<'Delegate,'Args>

Full name: Microsoft.FSharp.Control.Event<_,_>

--------------------
new : unit -> Event<'T>

--------------------
new : unit -> Event<'Delegate,'Args>
union case Event.SomethingHappened: Event
val decide : state:State -> command:Command -> Event list

Full name: Why FSharp.decide
val state : State
val command : Command
Multiple items
module Event

from Microsoft.FSharp.Control

--------------------
type Event<'T> =
  new : unit -> Event<'T>
  member Trigger : arg:'T -> unit
  member Publish : IEvent<'T>

Full name: Microsoft.FSharp.Control.Event<_>

--------------------
type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
  new : unit -> Event<'Delegate,'Args>
  member Trigger : sender:obj * args:'Args -> unit
  member Publish : IEvent<'Delegate,'Args>

Full name: Microsoft.FSharp.Control.Event<_,_>

--------------------
new : unit -> Event<'T>

--------------------
new : unit -> Event<'Delegate,'Args>
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val apply : state:State -> event:Event -> State

Full name: Why FSharp.apply
val event : Event
val replay : events:Event list -> State

Full name: Why FSharp.replay
val events : Event list
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

Full name: Microsoft.FSharp.Collections.List.fold
type State =
  {MyCurrentState: string;}
  static member empty : State

Full name: Why FSharp.State
property State.empty: State
Fork me on GitHub