本日の作業
本日は鎌倉もくもく会184回目でした。尚、来週のもくもく会はOOCへ行くので休み。
✅ DMMFの関数型プログラミングの実装でfp-tsを使うので学習
🚴 分報・日報・ユーザに関する設計・実装
🚴 Server側のDMMFの実装
サインインの実装
認証画面実装
認証ロジック実装(主にClient側)
Server側の認証チェック実装
Client側の認証チェック実装
🛑 🚴 イベントストーミングとサービスブループリンの融合についてzennにまとめる(次のもくもく会で書く予定)
fp-tsとDMMF
fp-tsはTypeScript用の関数型プログラミングライブラリで、代数的データ型や関数型のエラーハンドリング、データ変換といった関数型プログラミングの概念をTypeScriptで扱うためのツールが揃っています。
DMMFはDomain Model Made Functionalとある通り関数型プログラミングでドメインモデルやドメインロジックを表現しつつインフラストラクチャーやアプリケーションなどのレイヤーとのやり取りを行うものなのでfp-tsのいくつかを使って実装を進めていく方が良さそうです。
次のコードは書籍「Domain Modeling Made Functional」のサンプルコードのTypeScript版とのことなのでコードを読んで理解を深めました。
大まかな流れとしては次の感じ
Event Stormingでドメインイベントと集約・境界付けられたコンテキストを抽出&定義
ドメインロジックの文書化
1の流れを自然言語として記述することでコードを書く前に諸々整理することになる。Event Stormingと同じ感じなので場合によってはなくても良さそう。READMEなどで残しておけばメンバー間で共有できるのでそういう意味では書いた方が良さそう。
集約・command・Domain Eventの型定義とzod schemaの定義
実例のコード(OrderTaking)を見ました。上から順に読めばわかるんですけど、PlaceOrder.Implementation.tsに型定義とzod schemaと実装が混在していますが、これは適宜ファイルを分けるなどした方がコードとしてはわかりやすいのではないかと思いました。
集約とイベントの実装
集約
priceOrder(注文する?)はコードを見る限り、Event Stormingでいうところのview model(getProductPrice)をD.I.(依存性注入)してくるのと、commandで入力を受け付けて各値のバリデーション(toXXXとなっているものがそれ)したものを再帰関数の引数でD.I.している感じです。
それを踏まえてzodで集約全体の検証して問題なければデータを返す感じと思います。
ここで言う各値は値オブジェクトやローカル(サブ)エンティティに相当するものと思いますが、OOPではないのでそれぞれの値の妥当性をzodで検証してそれらで構成したものが先に集約の型定義したものと一致するように実装するといった手順なのかなと思います。
OOPでやる場合もTypeScriptでとなると値の検証にzodを使うケースがあると思いますのでやっていることは殆ど同じで書き方と捉え方が少し異なるといった感じでしょうか。
イベント
イベントは「注文確認した→注文した(→支払いした)」という感じでコメントアウトしてあるstepがそれぞれに相当しており、先に書いた集約を各種関数の中でイベントの詳細なロジックなどが記載されています。支払いについてはこのコード上では見当たらず検証だけするぽい?
尚、この関数の中で永続層などとのやりとりはせずロジックにのみ集中します。ChatGPTに雑に聞いたり、ネット上の記事の中ではこの関数の中で永続層とやり取りしているものがありますが、それをやるとDMMFの思想から外れる上責務分離や関心の分離がうまくいかなくなるので注意が必要かと思われます。て、それはOOP DDDでも同様。
イベントの生成
最初にorderPlacedとbillingのイベントを先の実装を元に生成している様ですが、billngの方は支払い可能な注文をしたかどうか検証しているが、orderPlacedは特に生成において条件はない様なのでそのまま代入している様子。このbillingにあるのがEvent Stormigのポリシーぽいですね。
あとはfp-tsでのデータを他の層で使えるデータに変換したりするヘルパーの実装を踏まえて先に述べた「注文確認した→注文した→支払いした」というドメインイベントの順に処理を進める様に実装されてあります。
ここで、各ドメインイベントの入力・検証・ロジック・出力をpipeで繋げて、最後に結果をflatでオブジェクトにして返してるぽいですね。
実行
最後のplaceOrder(発注)で実行しています。
ちなみに、各種イベントの生成時にあるpipeの中に永続層とのやり取りを行うのか、次の実行を踏まえてできたまとまったデータをもってやり取りするのかがここまでではわからなかったです。
とりあえずまとまったものをドメインイベントの順序に合わせてDBに用意しているイベントエンティティに追加していき、最後にリソースをupdateするという感じかと今のところは思ってます。もうちょい調べるのと実際に実装しながらこの辺は学んで行こうと思います。
その他、メモ
DMMF、まだ自分の実装をしていないのでなんともですが、関数型に慣れてないメンバーがいると辛いよってChatGPTと壁打ちした時に言われたのまさに実感してます。オブジェクト指向の経験がないとかまでになるとどっちも学習コストは高いですが、幾分オブジェクト指向の方がコード的には読みやすいなと思います。ただ、関数型プログラミングの方はやはり流れについてはわかりやすいのでメンバーの経験と学習意欲みたいなのを見てどうするか決めるないと大変なことになりそう。
本日のもくもく会後のランチは参加者の皆さんと鎌倉の隣、逗子市の小坪港まで歩いて行き(片道3km)海鮮丼とマグロ餃子でした。帰りも歩きだったのでちょっとした散歩に。