Event StormingからDMMFのI/F実装へ ─ 個人開発者向けのサービスの開発記録 #50

tyshgc
·

タイトルのフォーマット変えてみました。

{{トピック}} - 個人開発者向けサービス開発記録 #{{Number}}

自分で見返すときに探すのが難しくて…。過去のもちょっとづつ変えていこうかな。

本日の作業

  • 🚴 分報に関する設計・実装

    • 🚴 Server側のDomain Eventの実装

    • 🚴 Database(Prisma)の設計・実装

  • Supabaseの設定と開通

    • Supabase Auth

    • 🚴 Supabase Database

  • 🛑 🚴 イベントストーミングとサービスブループリンの融合についてzennにまとめる(休日にやる)

Event Storming

全体の仕組みは昨日の日報にまとめました。

分報に関するDomain Storming

Client側の実装 ─ ドメインイベントまで

ドメインイベント「分報を記録した」にフォーカスを当てて考えます。ドメインイベントはその中にさらにフローがある様なのでそれを自然言語で記述すると良いとあります。

ちなみにこの記事、ドメインイベントを過去形で記述していないのでブロックの色で判断するにオレンジがドメインイベント的にどうなのだろう?というのが注文の「在庫を確認 "する"」にありますが、注文される→注文されたの後にポリシーとコマンドがないと自然言語があの形になった経緯がよくわからない。

また、分報ドメインイベントをさらに細かくするという観点では少しあるがここまでの自然言語を書くほどの何かがなさそう。というのも分報は書くだけなので、それ以外の副作用がない。

なので、一旦自然言語でこの手順通りではなく「分報を記録した」ドメインイベントについて少しその中身を掘り下げてみました。

  • command: 分報を記録する

    • 分報(本文)を入力する

      • 本文の入力内容の書式(Markdown・Notion like)に異常がないか検証する

    • 分報を保存する

      • 記録日時を保存する

      • 公開のタイミングを即時・予約日時・任意のタイミングのいずれかで設定する

      • 公開範囲を開発者本人のみ・フォロワー全員(・除外したフォロワー以外のフォロワー)・ユーザ全員(・除外したユーザ以外全員)のいずれかで設定する

  • aggregation: 分報

  • domain event: 分報を記録した

    • policy: 非公開のまま

      • view model: 分報一覧

    • policy: 即時公開

      • command: 任意の分報を公開する

        • 分報の公開ステータスが「公開」か確認する

      • aggregate: 分報

      • domain event: 任意の分報が公開された

      • policy: 通知が許可されているフォロワー

        • command: 任意の分報の公開を通知する

        • external system: 通知

        • domain event: 通知が送信された

          • view model: Notification

          • view model: メール

          • actor: フォロワー

分報集約

  • 本文(Markdown・Notion likeで本文編集)

  • 記録日時

  • 公開タイミング [ 即時 | 予約日時 ]

    ※日報に含める場合は日報公開と合わせる

  • 公開ステータス[ 公開 | 非公開 ]

  • 公開範囲 [ 開発者本人のみ | フォロワー全員( | 除外したフォロワー以外のフォロワー) | ユーザ全員( | 除外したユーザ以外全員) ]

自然言語に書き換えるのはEvent Stormingから集約の定義やEvent Stormingに書ききれない条件や列挙を抽出して定義することが一旦のゴールだとしたらこれからDMMFで実装する際にまずは「分報集約」をinterfaceで定義してみます。

尚、集約のinterfaceを定義していますが、実はNotionで概念をモデルリングした通りになりました。

雰囲気で概念モデリングし、Event Stormingでフローを分析し、再度概念モデリングしみたいなイテレーションが精度高めそうだし、さらにこれにRDRAの一部を導入してみると条件や列挙・状態なども明らかになっていきます。その過程でinterface定義して実装を少しづつ進めると良い。また、DMMFじゃなくOOP DDDでも同様に進めるのがよさそうです。

余談

参考記事のコードはtRPCを使ってロジックは完全にBackend(Server)に寄せていてFrontend(Client)はuseFormを使ってzodでバリデーションするくらいになってる。そのくらい薄くてもいいと思うけど、バリデーションを画面に関することとするとコードのドキュメント性が低くなってどこで何やってるのかが一通りコードみないとわからなかった。こういうのをどこまで気を使って(?)やるかは永遠に答えが見つからない。

その他、メモ

Feature Sliced DesignとOOP DDDの連携と状態管理について

Feature Sliced DesignのEntitiesにHooksでUseCaseを実装してEntitiesをCompound patternにして親にStore用のuseState持たせ、そこに集約オブジェクトとフィールド毎のメッセージと表示の状態持たせてそれをContextとで伝播させる様にした。

これはFSDの思想に則っていてかつコードのインデックス性が整理されると思います。

  • View Modelが不要なので状態管理ライブラリなしで済んでいます。

  • Contextを薄い状態管理ライブラリに置き換えても良いと思います。ContextだとuseEffectなど初期値のセットを自分で頑張る必要があり。

Feature Slieced Designの概念を拡張する

Feature Sliced Designのレイヤールールについてそのまま使うより次のように概念を少し変えて使う方が良さそう。

  • Shared ─ 再利用性がありドメイン知識を持たないUIパーツ・UIヘルパー群。

  • Entities ─ 集約サービスとそれに関わるUI群。

  • Features ─ Entitiesに依存したプロセスやユーザタスクに沿ったレイヤー。

  • Widgets ─ Featuresとそれらの補助(見出しや説明など)で構成される画面上のブロック。

  • Pages ─ Widgetsを組み上げて構成される画面。

しかし、WidgetsはFeaturesが複数存在しなければ必要ない様な気もしなくもない。あとRemixの場合はWidgetsに<Outlet />に入るSub Routesがそれということにしておけばいい様にも思う。

音楽と集中力

作業中のBGM、最近はHania Raniばかり。ポストクラシックやの気鋭のポーランドのアーティストで異常に作業に集中できる。電子音を使っているけど尖った音がないところにアコースティックピアノが絶妙にマッチしているところが心地よい。

認知工学とUIデザイン

長いのでちょっとづつ読みます。

← #49 #51 →

@tyshgc
デザインファーム及びスタートアップ(上場)などを経てフリーランスとして、様々なスタートアップや大手企業の新規事業の立ち上げ期における事業設計・アプリケーションの設計・開発、サービスのUX分析とデザインとエンジニアリングの両軸でお手伝いさせていただいています。 現在、個人開発者向けの支援サービスを個人開発中。 X Account: @tyshgc