「関数型で表現するイベントソーシングの実装とその教育」について登壇しました
株式会社ジェイテックジャパン CTOの高丘 @tomohisaです。2023年3月24日に第四回関数型プログラミング(仮)の会の5分間のLTに参加させていただきました。以下はその資料です。
2023/12/17追記:
ジェイテックジャパンで開発してきた、イベントソーシング・CQRSフレームワーク、「Sekiban」をリリースしました! www.sekiban.dev/jp/
いかに画像を含めて、簡単に記事の内容を説明します。
イベントソーシング = 関数型?
イベントソーシングの提唱者である、Greg Young (グレッグヤング)は、よくイベントソーシングと関数型プログラミングを結びつけています。
2014年のGreg Youngの講演の文字起こしが提供されていました。その部分の一部を引用します。 Transcript of Greg Young's Talk at Code on the Beach 2014: CQRS and Event Sourcing
By the way, all of this comes back to functional programming as well.
Event Sourcing is a functional data storage mechanism.
How many of you have done functional programming before?
Okay, for all of you guys I'm going to simplify Event Sourcing for you.
Current state is a left fold of previous behaviours.
Simple! A snapshot is a memorization of your left fold, nothing more.
A snapshot is just me saying that at event 4 this is
what the state of this projection was.
How often do our events change? Never: they're immutable.
So when would that snapshot ever go bad at event number four? Never.
簡単に和訳したものが以下になります。
ちなみに、これらすべては関数型プログラミングにも関連しています。
イベントソーシングは、関数型データストレージメカニズムです。
皆さんの中で関数型プログラミングをしたことがある人はどれくらいいますか?
分かりました、それでは関数型プログラミング経験者の皆さんにイベントソーシングを簡単に説明しましょう。
現在の状態は、以前の振る舞いの左たたみ込み処理です。
簡単でしょう!スナップショットは、左畳み込みの途中経過を記憶するだけです。
スナップショットとは、イベント4でこのプロジェクションの状態がどうであったかを示すものに過ぎません。
イベントはどのくらいの頻度で変更されますか?答えは「決して」変更されません。
それらはイミュータブル(不変)です。
では、イベント番号4のスナップショットがいつ破損することがありますか?答えは「決して」ありません。
このように、イベントソーシングはとても関数型向きの理論だというのがわかります。
イベントソーシングの概念を簡単に図式すると以下のものになります。
-
- ユーザーの意思を反映したコマンドを受け取り、実行します
- コマンドハンドラーには依存の注入、副作用があります
- 実行した結果、イベント(複数可能)を保存します
-
- 集約毎、もしくは複数集約のイベントとステータスを回して状態を作成する
上記のコマンドとクエリーの責務を分離していることから、イベントソーシングはCQRS(コマンドクエリ責務分離)とセットに語られることが多いです。
コマンドハンドラーとは
コマンドハンドラーは、ユーザーの行いたいアクションをデータとして受け取って、その実行を行う機能です。これを行うために対象の集約の状態や、他の集約の状態などを参照したり、外部サービスの依存関係を取得したりして実行する処理となります。ですので、純粋関数ではなく、副作用のある処理とはなりますが、処理の流れとしては、コマンドを受け取って、イベントを出力する処理となります。
Greg Youngの初期の実装ではオブジェクト指向的に実装されています。
私たちの作っているフレームワークも真似て作っていたのですが、これはコマンドを入力とし、イベントを出力する関数だということに気がつき、現在は関数的な形でコマンドハンドラーを実装しています。
イベントから、集約の状態を取得するためには
イベントから集約を取得する方法に関しては、イベントのリストをreduceして集約の状態を生成するというのが基本的な形となっています。これは純粋な関数として実装が可能です。
これも、Greg Youngの初期の実装ではオブジェクト指向的に実装していたのですが、Event.OnEventという形で、純粋に受け取ったものから調理してリターンする形にすることにより、関数的な形で記述できるようにしました。
プロジェクションに関しても同様
どのように教えたか
イベントソーシング、関数型的なプログラミングに慣れてない方に使っていただく際には、ドキュメントやサンプルプログラムを書くことに加えてペアプロを多用しました。まず私が書いて、真似して書いていただくという形で、ドライバーを交代しながら行うないました。疑問ができたらまたペアプロを行うというのを続けることにより、疑問は減ってきたようです。
使っている方まで関数型思考になったわけではないと思いますが、関数型のフレームワークを使うことにより、入力と出力にフォーカスしてプログラミングできるので、慣れてくると作りやすいと感じていただけたようです。
教えるために作ったドキュメントとサンプルプログラムをChatGPTに読ませたら、かなりの精度でプログラミングしてくれるので、これからはこれで叩き台を作ってから修正してみるようにも進めたいと思います。
まとめ
イベントソーシングをC#で関数を意識してかけるフレームワーク「Sekiban」は現在オープンソースでリリース準備中で、できれば2023年春にリリース出来ればと考えています。
私もまだ関数型初心者なのですが、使えば使うほど、関数型プログラミングを上手く使えば、業務やドメインを綺麗に表現でき、メンテナンス性の高いシステムを作れると感じています。これからもよいものとしていきたいと思います。
Discussion