Closed9
[WIP]新幹線予約システムをドメインモデリングしてみる
モチベーション
- ICONIXプロセスの練習
- ロバストネス分析の美味しさがよくわかってないから、それを理解できるようになる事を期待
- モデリング手順の整理
- Zenn使ってみたい
- 今年も終わりだし、一個くらいなんかしらアウトプットしたい
- とはいえ体型だった知識をまとめるのはハードルが高い
- スクラップだったら雑に思考過程まとめるにはちょうど良い気がした
- PlantUMLが好き
要件の洗い出し
RDRAでは要望/要求/要件のように整理していくが、今回は大体要件が決まり切ってるので想像で書く
要件一覧
- 空いている席の検索
- 空いている全ての席を検索したい
- 空いている指定席を検索したい
- 空いている自由席を検索したい
- 空いている窓側の席を検索したい
- 喫煙ルームに近い車両から席を検索したい
- トイレに近い車両から席を検索したい
- 予約
- 出発地点〜到着地点までの
- 指定席or自由席を予約したい
- 並びの座席で複数同時予約したい
- 出発地点〜到着地点までの
- 変更
- 予約中の席から他の席に変更したい
- キャンセル
- 予約中の席をキャンセルしたい
- 予約の確認
- 自分の予約済みの席一覧を確認したい
- 過去に予約した席を確認したい
- 通知
- 予約完了したらメールで知らせてほしい
ドメインモデルv1(用語集)を作成する
ICONIXの文脈ではドメインモデルと表現しますが、DDDの文脈のドメインモデルとは意味するところが違うので注意が必要
要件から名詞を抜き出す
- 空席
- 指定席
- 自由席
- 窓側の席
- 喫煙ルーム
- 車両
- トイレ
- 予約
- 出発地点
- 到着地点
- 並びの座席
- 複数同時予約
- 予約中の席
- 予約済みの席一覧
- 過去に予約した席
- 通知
- メール
PlantUMLで[card]で定義し、まとまり事にざっくりと段落で区切る
個人的にICONIXのこの工程はPlantUMLやmarmaid.jsなどの、テキストでモデリングできるツールが相性良さげ。
plantumlのプレビューはIntellijを使う。マルチカーソルが使えるエディタなら、一気にTypeを書き加えられるので便利。
後の工程でcard同士を関連づけていくのですが、一旦段落でまとまりを整理しておくと楽です。
段落で整理していく中で気づいた、「運賃」や「席の種類・状態」といった概念もこの時点で追加しておきます。
@startuml
card 新幹線
card 系
card 車両
card 号
card 席一覧
card 席
card 種類
card 指定席
card 自由席
card 状態
card 予約済み
card 空席
card 配置
card 窓際の席
card 喫煙ルームに近い
card トイレに近い
card 履歴
card 予約一覧
card 予約
card 出発地点
card 到着地点
card 運賃
card 指定席料金
card 自由席料金
@enduml
card同士を関連づけていく
汎化と集約関係を使って、cardを関連づけていく。
この時、関係性がよくわからないものは、一旦棒線でつなげておけばよい。(関係性は後の工程で明らかになる可能性が高く、最初はそこに悩む時間がもったいない為。)
@startuml
card 新幹線
card 系
card 車両
card 号
card 席一覧
card 席
card 種類
card 指定席
card 自由席
card 状態
card 予約済み
card 空席
card 配置
card 窓際の席
card 喫煙ルームに近い
card トイレに近い
新幹線 --* 系
新幹線 --* 車両
車両 --* 号
車両 --* 席一覧
席一覧 --* 席
席 --* 種類
種類 <|-- 指定席
種類 <|-- 自由席
席 --* 配置
配置 <|-- 窓際の席
配置 <|-- 喫煙ルームに近い
配置 <|-- トイレに近い
席 --* 状態
状態 <|-- 予約済み
状態 <|-- 空席
card 履歴
履歴 --* 席
card 予約一覧
card 予約
card 区間
card 出発地点
card 到着地点
card 運賃
card 指定席料金
card 自由席料金
予約一覧 --* 予約
予約 --* 区間
区間 --* 出発地点
区間 --* 到着地点
予約 --* 運賃
運賃 <|-- 指定席料金
運賃 <|-- 自由席料金
予約 --* 席
@enduml
ユースケースを洗い出す
「要件」からユースケースを考える。「メールで完了通知」は「予約完了」のドメインイベントを発行して...などややこしそうな気がしたので一旦無視する
指定席とか、自由席とか、喫煙席に近い、とかは座席予約時に絞り込み機能などで提供すべきなのかな?ICONIXでは「ドメインモデル 」や「ユースケース記述」「ロバストネス図」は常に更新し続ける前提なので、細かい事は一旦気にしない
ユースケース一覧
- 列車を検索する
- 席を予約する
- 予約中の席を他の席に変更する
- 予約中の席をキャンセルする
- 予約履歴を確認する
ユースケース図
ユースケース毎にユースケース記述を書く
- ユースケース記述は、ユーザーとシステムとの対話を記述する
- 使用する用語は「ドメインモデル 」で洗い出したものを使用する
- ユースケース記述を書く中で用語に違和感がある場合は、用語を修正し、ドメインモデルに反映する
- 新たな用語が登場する場合は、ドメインモデルに追加する
- これが目的でもある(多分)
- 全部書き切って、最後でも良い(多分)
- 個人的に箇条書きで
ユーザー
のアクションとシステム
の振る舞いを段落で分けるのが好み - GUIの場合は、システムがある画面を表示するところから書き始めるので、最初の行は
*
にしてみた- 段落を他と揃えたいだけなので特に意味はない
- 今回は他のユースケースへの参照を
(hogehoge)
で表現してみた
列車を検索する
晴れの日
-
*
- システムは
時刻・運賃検索画面
を表示する
- システムは
-
予約者
は出発駅
と到着駅
、出発日時
を入力し、検索
ボタンをクリックする- システムは
条件
に沿った列車
を列車一覧
から検索し、検索結果画面
を表示する
- システムは
雨の日
-
出発駅
/到着駅
が未入力- エラー表示し、再度
時刻・運賃検索画面
を表示する
- エラー表示し、再度
-
出発日時
が未入力- エラー表示し、再度
時刻・運賃検索画面
を表示する
- エラー表示し、再度
席を予約する
晴れの日
- (列車を検索する)
-
予約者
は検索結果画面
から任意の予約
ボタンをクリックする- システムは指定された
列車
の運行情報
から、検索条件
の区間
に絞り込んだ時刻表
を一覧表示する - 各時刻の行には、席の種類毎の
運賃
(指定席料金
,自由席料金
,グリーン席料金
)を表示する。
- システムは指定された
-
予約者
は希望する席の種類をクリックする- システムは選択された席の種類から、
空席
状態の席を一覧表示する
- システムは選択された席の種類から、
-
予約者
は絞り込みタブ
をクリックする- システムはドロップダウンで
窓際
,喫煙ルームに近い
,トイレに近い
,2人並び席
,3人並び席
を表示する
- システムはドロップダウンで
-
予約者
は任意の絞り込み
をクリックする-
窓際
が選択された場合- システムは
空席状態
のC席
またはE席
を一覧表示する
- システムは
-
喫煙ルームに近い
が選択された - システムは
喫煙ルーム
を挟む号車
から、空席状態
の席
を一覧表示する -
トイレに近い
が選択された場合 - システムは
トイレ
を挟む号車
から、空席状態
の席
を一覧表示する -
2人並び席
が選択された場合 - システムは隣同士で
空席状態
の席
を一覧表示する -
3人並び席
が選択された場合 - システムは3席続けて
空席状態
の席
を一覧表示する
-
-
予約者
は任意の席
をクリックする- システムは
乗車日
,系
,出発時刻/到着時刻
,席の種類
,料金
を表示する
- システムは
-
予約者
は予約ボタンをクリックする- システムは選択された
席
を予約
する
- システムは選択された
雨の日
- 希望した席の種類で
空席
が0だった- エラー表示し、再度席の種類毎の
運賃
(指定席料金
,自由席料金
,グリーン席料金
)を表示する。
- エラー表示し、再度席の種類毎の
-
予約
された席が既に予約済み
だった- エラー表示し、再度
空席
状態の席を一覧表示する
- エラー表示し、再度
予約履歴を確認する
晴れの日
-
*
- システムは
予約者
のマイページを表示する
- システムは
-
予約者
は予約履歴
ボタンをクリックする- システムは
予約履歴一覧
画面を表示する
- システムは
予約中の席を他の席に変更する
晴れの日
- (予約履歴を確認する)
-
予約者
は変更したい予約
の詳細
ボタンをクリックする- システムは
予約詳細
を表示する
- システムは
-
予約者
は変更する
ボタンをクリックする- システムは
予約済み
であった列車の区間
に絞り込んだ時刻表
を一覧表示する - 各時刻の行には、席の種類毎の
運賃
(指定席料金
,自由席料金
,グリーン席料金
)を表示する。
- システムは
- 以下(席を予約する)[
予約者
は希望する席の種類をクリックする]に同じ
雨の日
- 予約していた電車の運行時間を過ぎていた
- エラー表示し、
予約詳細
画面を表示
- エラー表示し、
予約中の席をキャンセルする
晴れの日
- (予約履歴を確認する)
-
予約者
は変更したい予約
の詳細
ボタンをクリックする- システムは
予約詳細
を表示する
- システムは
-
予約者
はキャンセルする
ボタンをクリックする- システムは
予約
のキャンセル画面を表示する
- システムは
-
予約者
はOK
ボタンをクリックする- システムは
予約者
の予約
のキャンセルする
- システムは
雨の日
- 予約していた電車の運行時間を過ぎていた
- エラー表示し、
予約詳細
画面を表示
- エラー表示し、
ユースケース記述の内容をドメインモデルに反映する
- ユースケース記述に出てきた用語を初期のドメインモデルに反映する
- 更新/追加した項目は色を変えてみた
- 予約詳細が
出発時刻
や到着時刻
を持つのは実際にそうなるかはまだわからない- 乗車する列車の
系
と区間
が決まれば、↑の値は一意に定まるはず
- 乗車する列車の
-
席の種類
と席の料金
が離れているのが気になる- 予約詳細は実は
料金
を持たなくて良い?
- 予約詳細は実は
ロバストネス図
- 席のキャンセルからは、特に新しいオブジェクトを発見できそうになかったので割愛
- 改めて「ユースケース駆動開発実践ガイド」を読むと、コントローラには「アクターの振る舞い」と「システムの振る舞い」がある事に気付いた
- その内の「システムの振る舞い」が、おそらくDomain層のモデルのメソッドになったり、Domain Serviceになったりするのでは?
- コントローラーの振る舞いを遂行する為にどんなオブジェクトが必要か?と考えると、新たなオブジェクトが発見しやすい事がわかった
- 例えば、「料金を算出する」コントローラーがあれば、料金を算出する為には「料金表」とか「基本料金」とかが必要では?ってなる
予約中の席を他の席に変更する
列車を検索する
予約履歴を確認数
席を予約する
ドメインモデル v3
- ロバストネス図を書いてる途中に発見した概念や、その後ドメインモデルを整理する中で連鎖的に発見した概念を追加
- ロバストネス図から発見したオブジェクトを追加しようとすると、既存のオブジェクトの今の関係性おかしくない?とか連鎖的に発生した
- 多分これはエヴァンス本で言う「ブレークスルー」に繋がる話かも?
- なんか微妙な感じだったけど隠れていた「暗黙な概念」を発見する事がきっかけで「リファクタ」→「より深いモデルの発見」みたいな話に通じそう
- とはいえ今はドメインエキスパートとかいなくて1人でやってる(予約システムのドメイン知識も皆無)ので、実際はどんな感じなんだろう
- 追加したcardは青にした
- 料金は予約対象の席から導かれるもので、料金オブジェクトと汎化関係で指定席料金、自由席料金、グリーン席料金が存在するのは違和感を感じたので削除
クラス図 v1
- 雰囲気で整理してみたversion1
- テストから書き始めてみて、使い勝手を確認するのが良さそう
- おそらくこのモデルは実装の過程で細かい部分はどんどん変わっていく
ChatGPTを使って、どれくらい簡略化出来るのか試してみたい
このスクラップは2022/10/12にクローズされました