Exploring F# through modeling #3

Introduction

In the quest of getting into F# we have explored modeling a rock-paper-scissor game. In the two earlier posts we made a Game aggregate and the GameHandler. In this post we’re going to do some refactoring and see what we could learn from that. The earlier posts could be found here;

In this post we’re going to do some refactoring and see what we could learn from that.

Restoring state

In the game aggregate we have the restore state function. This is our first target for refactoring. We want the GameHandler (part of the application) to hold the part of the step function, and letting the game just restore the state for each event.

Before

We added applyEvent to Game that now does the type matching. This way the GameHandler could restore state from a future snap shot (as pointed out in the comments from post #2).

After

In the handler we now fold the events, applying each event with our new applyEvent. Think of fold as the LINQ equivalent of Aggregate. The handler gives the initial default state to aggregate upon.

After

Storing events

The second target for refactoring is the way we store the events. In the GameHandler we have a map of aggregateId and a list of events. The load function simply returns the events for the given aggregate and the save does nothing. To be able to play the game and try this out, we need to change this.

Before

We are going to continue to store our events in memory in a map, but without any dummy events and also implement save. To do this we need to change/update the list of events (or the eventstore itself). Replacing the eventstore with an empty map. The save method now needs to check if there are any events for the aggregate and then append to the list of events. Due to this save changes name to append.

After

We now need to mutate the EventStore or each list of events in the EventStore map. F# is not big on mutating :) so we need to declare the EventStore as mutable to get away with it. This way we now have our in-memory persistence of events, enabling us to try this out.

C# interop – Trying it out

With the changes made to restoring state and persisting state, we’re now going to see how it feels like to use our Game from C#, to test and try out our solution.

We’re not going to look at testing of the Game aggregate in this post but simply playing a game end-to-end as two simplified integration tests.

First we create a CreateGameCommand with the name of the game and the move for playerOne and send it to the GameHandler. Now it’s time for player two to make a move. So we create a MoveCommand and passes that to the GameHandler. The two commands should result of the four events in total (GameCreated, MoveMade, MoveMade, GameEnded). Lazily we here just check the count :p

Lacking projections to check the result, we simply check the GameEndedEvent for the result of the game (we could check the game(state) itself).

Note the “IsPlayerTwoWin” property that is exposed to C# to check the result.

Lessons learned

  • We looked how to use mutable
  • We used fold for restoring state much like the C# starting point from post #1 Func
  • We used the Map.add function in the append function. Returning a new map in its immutable fashion.
  • We looked at using our Game from C#, pretty straight forward. The only thing notable here was the IsPlayerTwoWin. But what if we would have passed move as a string ? How would we get from string -> Move ? – Next time.

Conclusion

We’ve made the first refactorings to our game. There is still more to do. Maybe try commands and events as discriminated union. Testing in F#, using the a real eventstore (geteventstore.)

Enjoy!

Trackbacks for this post

  1. F# Weekly #27, 2014 | Sergey Tihon's Blog
  2. F# Weekly #28, 2014 | Sergey Tihon's Blog

Leave a Reply