2026年10月31日土曜日

Cozyモデル駆動開発/ユースケース/conflicts

本稿では、ユースケース間の関係の一つであるconflicts(競合・排他関係)を取り上げます。

前回のcollaboratesでは、複数のユースケースの結果を合わせて業務を進める構造を整理しました。今回は、同じ業務対象について、両方を成立させてはいけないユースケースを扱います。

例えば、一つの注文に対して、出荷と出荷前の取消しをそれぞれ独立に進めると、取消しを受け付けたのに商品が発送される場合があります。conflictsでは、このような組合せを明示し、どの条件でどちらを採用するかを定めます。

conflicts

  • マージモード : Branch
  • マージ点 : 条件分岐
  • 機能 : 排他シナリオ
  • 由来 : Goal/Feature modeling

本連載では、conflictsを、指定した対象と条件のもとで、二つのユースケースを両立させない関係として扱います。シナリオを合成するときは、両方を進める経路ではなく、条件によって一方を選ぶ分岐として構成します。

関係を記述する際には、次の三点を定めます。

  • 何について排他的に扱うか
  • どの状態や期間に排他が必要か
  • 両方の要求が来たとき、どの規則で選択するか

出荷と取消しの例なら、排他の対象は同じ注文です。別の注文の出荷や取消しまで止める必要はありません。また、発送後の返品は別の業務として扱います。注文の生涯を通じて、あらゆる取消しや返金と出荷を一律に排他的にするわけではありません。

関係の意味と分岐の選択

UseCase A が UseCase B とconflictsするとは、定めた範囲でAとBを同時に成立させてはならないことを意味します。

同じ判断対象をs、分岐として採用することをSelectedとすると、選択の制約は次のように表せます。

not (Selected(A, s) and Selected(B, s))

これは、両方を採用しないという条件です。必ずどちらかを採用するという条件は含みません。要求がまだない場合や判断に必要な情報が不足している場合には、どちらも選ばない状態があります。

また、conflictsは両立しない関係を表し、Aを優先するという意味までは持ちません。本稿で扱う排他の意味は対称ですが、どちらを選ぶかという選択規則には優先順位を付けられます。

例えば、次のような規則が考えられます。

選択規則モデルで定める内容
状態に応じて選ぶ現在の状態で受け付けられる要求を選ぶ
一方を優先する両方が選択可能な場合に適用する業務上の優先順位を定める
先に確定した要求を採用する共通の受付箇所で、状態変更を先に確定できた要求を選ぶ
判断を保留する情報不足や判断不能の場合に保留し、確認へ回す

Branchというマージモードは、この選択を合成シナリオの条件分岐へ反映する方針です。conflictsだけから、業務上の選択規則が自動的に決まるわけではありません。

記述例

Pieris Booksで、出荷準備が整った注文を扱います。前回の在庫予約と支払い承認が揃った後、倉庫から出荷要求が届く一方で、利用者から取消要求が届く可能性があります。

ここでは、次の業務規則を置きます。

  • 出荷準備済みの注文について、出荷または出荷前の取消しを受け付ける
  • 先に状態変更を確定した要求を採用する
  • 出荷への着手を確定した後は、出荷前の取消しを受け付けない
  • 取消しへの着手を確定した後は、出荷を受け付けない

「先に」は、利用者が画面を操作した時刻ではなく、注文を管理する側で状態変更を確定した順序を指します。

以下は関係と契約を説明するための記述例です。Cozyの実装済み構文を示すものではありません。

usecase ShipOrder
  pre:
    - 注文が出荷準備済みである
    - 有効な在庫予約と支払い承認が揃っている
  selection:
    - 注文を出荷中へ変更して、出荷への着手を確定する
  post:
    - 注文が出荷済みである
    - 出荷結果が記録されている
usecase CancelOrderBeforeShipment
  pre:
    - 注文が出荷準備済みである
  selection:
    - 注文を取消処理中へ変更して、取消しへの着手を確定する
  post:
    - 注文が取消済みである
    - 在庫予約と支払い承認の解消結果が記録されている
usecase ShipOrder conflicts CancelOrderBeforeShipment
  scope:
    - 同じ注文に対する、出荷準備済みからの分岐
  selection-policy:
    - 状態変更を先に確定した要求を採用する

各ユースケースの事前条件は、個別の要求を受け付けられる条件です。conflictsは、それぞれが条件を満たす場合でも、両方への着手を確定してはならないことを表します。

そのため、個々の契約に加えて、分岐を選ぶ共通の判断が必要になります。

状態機械への対応

この例の選択規則は、注文の状態と許される遷移として整理できます。

現在の状態出荷要求出荷前の取消要求
出荷準備済み出荷中への遷移を試みる取消処理中への遷移を試みる
出荷中既存の出荷処理へ対応付ける出荷に着手したことを通知し、受け付けない
取消処理中取消しに着手したことを通知し、受け付けない既存の取消処理へ対応付ける
出荷済み出荷結果を返す出荷前の取消しは受け付けず、返品等の案内へ進む
取消済み受け付けない取消結果を返す

出荷準備済みから出荷中へ移った注文は、取消処理中へ進む開始条件を満たさなくなります。逆の場合も同様です。排他の規則が、遷移の可否として表れます。

ユースケースは利用者や業務担当者の要求と結果を表し、状態機械は対象が取り得る状態と遷移を表します。両者を対応付けることで、「取消しへの着手後に出荷が始まる経路がないか」をモデル上で確認できます。

ワークフローでは、この選択を出荷経路と取消経路の分岐として表します。ユースケースで定めた排他条件、状態機械の遷移条件、ワークフローの分岐条件を揃えることで、要求から処理の構成まで同じ規則を引き継げます。

同時に届く要求を扱う

状態と条件を定めても、それぞれの処理が別々に状態を読み取るだけでは排他を維持できません。

例えば、出荷側と取消側がともに出荷準備済みを読み取り、その後それぞれが処理を始めると、両方が事前条件を満たしたと判断してしまいます。

そこで、実行設計では、開始条件の確認と着手状態の更新を一つの確定操作として扱います。片方が先に確定した場合、もう片方は更新後の状態に基づいて要求を扱います。

モデルで定めること実行設計で具体化すること
排他の対象は同じ注文注文を識別し、判断を同じ管理箇所へ集める
出荷と取消しの着手を両立させない条件確認と状態更新を不可分に行う
状態変更を先に確定した要求を採用する同時更新を検出し、採用されなかった要求を再判定する
同じ要求を重ねて実行しない要求の識別子で既存処理や結果へ対応付ける

不可分な更新は、トランザクション内のロックや、状態・版を条件とする更新などで実現できます。複数の実行拠点がある場合にも、同じ注文の選択を一貫して確定できる管理方式が必要です。

ここでconflictsが与えるのは、維持すべき業務上の規則です。その規則を状態と分岐へ落とし込み、実行基盤の更新制御と接続することで、実際の同時要求にも適用できます。

選択後の失敗と結果不明

分岐を選択したことと、そのユースケースが正常に完了したことは別です。

出荷中へ変更した後に、配送側の処理が失敗する場合があります。また、配送側では受け付けられたものの、応答が届かず結果が分からない場合もあります。

状況扱い
採用した処理が完了した結果を記録し、完了状態へ進める
外部処理を開始していないことが確認できた復旧条件に従い、再試行または選択のやり直しを判断する
外部処理の結果が不明である選択済みの状態を保持し、結果を照会する
外部処理がすでに成立していたその結果を反映し、必要なら別の取消し・補償手続きへ進める

結果不明のまま出荷準備済みへ戻すと、取消しを受け付けた後に出荷の完了が判明する可能性があります。選択をやり直せる条件には、外部処理の結果や、残っている責務を含めます。

同様に、取消処理中に在庫予約の解放が済んでも、支払い承認の取消しが未完了なら、取消処理を継続します。一部が終わったことだけで注文全体を取消済みにしないよう、正常終了の契約と進行状態を対応させます。

他の関係との組合せ

conflictsは、他の関係と組み合わせてシナリオ全体を構成します。

関係表すこと注文の例
collaborates複数の結果を合わせる協調在庫予約と支払い承認を揃える
precedesユースケース間の順序出荷準備を整えてから出荷へ進む
requires開始に必要な条件や前提出荷に有効な予約と承認を必要とする
ensures正常終了時に保証する結果取消完了時に予約と承認が解消されている
conflicts定めた範囲での両立を禁止する制約同じ注文の出荷と出荷前の取消しを両立させない

順序を付ければ両方を実行できる処理にはprecedesを使えます。出荷と出荷前の取消しは、順番を変えるだけでは両立しません。この場合は、conflictsによって採用する経路を分けます。

一方、前回の在庫予約と支払い承認は協調する関係です。その結果が揃った後に出荷と取消しの選択があるため、一つの業務の中に協調と排他の両方が現れます。

また、二つのユースケースが同じデータを更新するだけで、直ちにconflictsになるわけではありません。順序を整えれば両方の結果を受け入れられる場合は、データ更新の調整として扱えます。conflictsを記述する根拠は、業務上どの結果や進行状態を両立させてはいけないかにあります。

シナリオによる確認

排他関係のレビューでは、一方ずつの正常なシナリオに加えて、要求が重なる場合を確認します。

確認するシナリオ期待する結果
出荷準備済みで出荷要求だけが届く出荷経路を採用する
出荷準備済みで取消要求だけが届く取消経路を採用する
同じ注文に両方の要求が届く一方だけが着手を確定し、他方には採用されなかった理由を返す
同じ要求が再送される新たな処理を重ねず、既存の進行状態や結果を返す
異なる注文に出荷と取消しの要求が届く各注文の条件に従って独立に進める
出荷要求の外部処理が結果不明になる結果を確認するまで出荷前の取消しを新たに採用しない
発送後に取消要求が届く出荷前の取消しと区別し、返品等の業務へ案内する

これらの実例を、ユースケースの契約、ワークフローの分岐、状態機械の遷移と突き合わせます。両方が進めてしまう経路と、必要以上に別の注文まで止めてしまう制約の双方を確認できます。

まとめ

conflictsは、指定した対象と条件のもとで、ユースケース同士を両立させない関係です。排他の範囲と選択規則を定め、その規則を条件分岐と状態遷移へ反映します。

さらに、実行時の条件確認と状態更新を一つの確定操作へ結び付けることで、同時に届く要求にも排他を適用できます。選択後の失敗や結果不明を含めて扱うことにより、正常時の分岐から復旧時の判断まで、同じ業務規則で整理できます。

次回は、シナリオの置換を表すsupersedesを取り上げます。