状態遷移と、関連への波及 — 受注ライフサイクルの状態管理とイベント伝播
状態は遷移表に沿って変わり、変更は関連エンティティへ自動で波及する。その設計と、循環という落とし穴。
STATE業務エンティティは「状態」を持つ
通販基幹の業務エンティティ、たとえば受注は、一度作られて終わりではありません。入力途中の下書きから、内容が固まった確定、出荷の手配、そして受注確定へと、時間とともに姿を変えていきます。この移り変わりを場当たりのフラグで管理すると、どのフラグとどのフラグが同時に立ちうるのか、誰も説明できなくなります。Vegas ではエンティティに単一の「状態」を持たせ、その取りうる値と移り方を明示的に定義することで、この曖昧さを避けています。
- 入力中 — 編集の余地がある下書き段階。
- 確定 — 内容が固まり、後続処理の対象になる。
- 出荷登録 — 出荷の手配が組まれた段階。
- 受注確定 — 一連のフローが完了した段階。
TABLE遷移は「表」で定義し、可否を関数で判定する
どの状態からどの状態へ動けるかは、コードに散らばった条件分岐ではなく、遷移表という一つのデータとして持ちます。「入力中→確定は可、確定→入力中は原則不可」といった規則を表に集約すると、業務フロー全体を一望できます。実際の遷移要求が来たときは、現在状態と目標状態の組が表に載っているかをチェック関数が判定し、載っていなければ弾きます。分岐がデータになるため、フローの変更が表の編集に閉じ、レビューもしやすくなります。
LINK関連リンクを辿って変更が「波及」する
エンティティは孤立していません。受注は出荷や債権と結びつき、定期は受注を生みます。Vegas ではこれらの結びつきを有向の「関連リンク」として持ち、あるエンティティの状態が変わると、リンクを辿って関連先へイベントを流します。状態変更を受け取った状態 HUB がイベント基盤へ発火し、リンク先が自分の遷移表に照らして反応する、という流れです。
- 受注 → 出荷 — 受注確定が出荷側の処理を促す。
- 受注 → 債権 — 金額の確定が債権計上へつながる。
- 定期 → 受注 — 定期の稼働が子の受注を生成する。
利点は明快です。状態も波及経路もデータとして残るため、業務フローを宣言的に書け、「なぜこの債権が立ったのか」を関連リンクとイベント履歴から追跡できます。
CYCLE循環という落とし穴
この設計の弱点は、リンクの向きが健全であることに依存する点です。もし関連リンクに循環があると——親が子を指し、子が親を指すような状態——波及はループします。片方の取消が相手の取消を呼び、それがまた最初のエンティティへ跳ね返る。こうして意図しない取消・削除の連鎖が起きえます。厄介なのは、循環がデータとして混入しやすいことです。とくに移行データでは、本来一方向であるべき参照が誤って双方向に設定され、平常時には見えない循環が仕込まれることがあります(本連載で以前扱った移行データ起因の循環参照とも通じる話です)。
対策は伝播そのものの制御に尽きます。波及に順序と停止条件を持たせ、同じイベントを二度処理しない冪等性を担保することです。
- 停止条件 — 訪問済みの経路や深さ上限で波及を打ち切る。
- 冪等 — 同一状態への再遷移は無視し、連鎖の再燃を防ぐ。
- 順序 — 波及の適用順を定め、非決定的な結果を避ける。
TRADEOFF宣言性と、暴走リスクの綱引き
状態遷移表とリンク駆動の波及は、フローを宣言的に書ける強力な仕組みですが、代償があります。振る舞いがコードではなく定義データに宿るぶん、実行時の挙動はデータの正しさに左右されます。表やリンクが正しければ美しく回り、汚れていれば静かに暴走します。宣言的な柔軟さと引き換えに、循環検知・停止条件・冪等という「安全装置」を運用として持ち続ける必要がある——これがこの設計の本質的なトレードオフです。柔軟さを取るか、単純な手続き的処理の予測しやすさを取るかは、扱う業務の複雑さと、データの素性の確からしさで決まります。
状態は遷移表に、波及は有向リンクに宿らせると業務フローを宣言的に表せ追跡もしやすい。ただしリンクの循環は取消・削除の連鎖を招くため、循環検知・停止条件・冪等を安全装置として必ず備えること。