Tsuzura

状態遷移図の作り方

状態、イベント、ガード、許可・禁止・未決を表に整理し、図へ反映して実装とテストへ渡す方法です。

状態によって許可される操作が変わる機能では、同じ条件が画面、外部から呼び出す処理、データ更新、定期処理などへ分かれていると、判断が一致しているかを確かめる作業が必要です。独立した条件や組み合わせが増えれば、確認対象も増えることがあります。

状態遷移の設計では、対象が現在どの状態にあり、何が起き、どの条件を満たすと、次のどの状態へ移るかを先に決めます。許可する遷移、禁止する遷移、まだ決められない遷移を同じ表へ記録すれば、実装条件とテスト条件を同じ設計から取り出せます。

この記事は、状態遷移図を初めて作る人を対象にしています。読み終えると、一つの機能について、状態、イベント、遷移、ガード条件、初期状態、終了状態を空欄の設計票へ整理し、実装とテストへ渡せます。完成済みの業務例、UMLやSCXMLの完全な表記法、特定の作図ツールやコード実装は扱いません。

始める前に、対象の利用者、現行の処理と例外、対象外、必要な結果、受入条件を決めておきます。未決なら、先に要件と受入条件の決め方で一機能の範囲を整理します。個人情報、基幹データ、外部共有、認証連携を含む場合は、組織のルールに従ってIT、セキュリティ、個人情報保護などの担当者へ確認する範囲も決めます。状態遷移図は、未決の業務判断を自動で確定するものではありません。

なぜ状態遷移を設計するのか

状態遷移が役立つのは、同じイベントへの応答が、現在の状態や、それ以前に完了した処理によって変わる場合です。保持している過去の状態に関係なく、現在の入力条件と結果だけを対応させればよい場合は、入力条件と結果を並べる条件表で足りることがあります。

状態遷移の判断が複数箇所に実装される場合は、次の内容が同じ規則に従っているかを確認する必要があります。

  • どのデータから現在状態を判断するか
  • その状態で受け付けるイベントは何か
  • 追加条件を誰が、どのデータで確認するか
  • 許可しない操作へどう応答するか
  • 状態を変える処理と、通知や記録などの処理をどの順序で行うか
  • 途中で失敗した場合に、どの状態を正式な結果とするか

図を描くこと自体が目的ではありません。許可する変化を関係者が確認し、実装とテストが同じ規則を参照できることが目的です。状態の保存場所、誰にどの操作を許可するか(認可)、同時更新、失敗時の整合性が未決なら、図を完成扱いにせず、実装前の確認事項として残します。

状態・イベント・遷移を分ける

W3CのSCXML仕様は、状態、遷移、イベントを、状態遷移を扱う仕組みの基本概念として分けています。現在有効な状態でイベントが起き、対応する遷移が選ばれると、遷移先が新しい有効な状態になります(W3C SCXML 1.0 — Basic State Machine Notation)。

この記事では、次の五つを別々に記録します。

  • 状態: 現在どの段階や条件にあり、次に何を許可するか。画面名、ボタン名、処理名とは分ける
  • イベント: 遷移の判断を始める、すでに起きた事実。許可条件や、次にしたい処理とは分ける
  • 遷移: 現在状態から遷移先状態への変更。遷移中に行う処理とは分ける
  • ガード条件: イベントが起きたとき、その遷移を選べるかを決める追加条件。イベントそのものとは分ける
  • アクション: 遷移に伴う更新、記録、通知など。遷移先状態とは分ける

以下の分け方と設計票は、SCXMLの実装仕様やISTQBの公式テンプレートではなく、記事内で一つの機能を整理するための編集上の手順です。

状態

状態名と、「この状態と判断する条件」を一緒に書きます。同じイベントを受けたときの許可結果が同じなら、本当に別状態が必要かを見直せます。許可結果が異なるのに同じ状態名へまとめると、その違いはガード条件側に残ります。

この記事でいう基準データは、正式な現在状態を判断するために使うデータです。状態を複数のデータから計算する場合は、どのデータを基準に、どの処理が判定するかを記録します。画面に表示した値や、利用者側から送られた値だけで正式な状態を確定しません。

イベント

イベントには、発生元と必要な入力を記録します。発生元ごとに、認証の要否、入力が途中で変わっていないことの確認、重複、順序の入れ替わり、再実行をどう扱うかを検討します。イベント名だけでは、これらの条件を判断できません。

遷移・ガード・アクション

遷移は、現在状態とイベントだけで決まる場合もあれば、ガード条件が必要な場合もあります。SCXMLでは、イベントとガード条件の両方がある遷移は、イベントが一致し、条件が真になったときに選択対象になります(W3C SCXML 1.0 — transition)。

ガード条件には、判定文に加えて、使うデータ、確認する時点、確認する処理を残します。権限がある、入力が正しいという結論だけでは、実装者が同じ判定を再現できません。認可や入力検証の詳細は別に設計し、ガード条件から参照できるようにします。

アクションは、状態の変更とは別の項目です。状態変更の前後に何を行うか、アクションが失敗した場合に正式な状態をどうするかを決めます。業務上の判断が足りない場合は、設計担当者が未決事項と影響範囲を設計票へ記録し、判断の承認者へ確認を依頼します。

ガード条件と禁止遷移を決める

状態とイベントを列挙したら、組み合わせごとに遷移区分を付けます。

遷移区分 記録する結果
許可 ガード条件、遷移先、アクション、失敗時の正式な状態を決める
禁止 遷移先をなしとし、拒否時の応答、状態、記録を決める
未決 確認相手と期限を決め、結果が決まるまで実装対象にしない

禁止と未決を同じ空欄で表さないことが重要です。ISTQBのFoundation Levelシラバスでは、完成した状態遷移表の空セルを無効な遷移として扱います。一方、作成途中の空欄には、調査漏れや未承認も含まれます(ISTQB CTFL v4.0.1 §4.2.4(PDF))。この記事の空欄票では、各組み合わせへ許可、禁止、未決を明記し、未記入に意味を持たせません。

禁止した組み合わせでは、その遷移による状態変更を行いません。拒否応答、記録、通知など、遷移以外に必要な結果を決めます。状態を変える必要があるなら、その組み合わせは別の許可遷移として記録します。

同じ現在状態とイベントに複数のガード条件がある場合は、同時に成立する可能性と選択規則を確認します。SCXML準拠の実装ではSCXMLの選択規則に従い、それ以外では採用する実装方式で規則を決めます。優先する遷移を説明できない場合は、状態またはイベントの分け方を見直します。

初期状態と終了状態を決める

初期状態は、対象の管理を開始した時点で入る状態です。データ作成直後、既存データの移行直後、処理を再開した直後を同じ初期状態にできるかを確認します。複数の開始経路がある場合は、それぞれの開始条件と正式な初期状態を記録します。

終了状態は、対象の一連の処理が完了し、通常は次の遷移を受け付けない状態です。SCXMLでも、initialは開始時に入る既定状態、finalは処理完了を表す状態として区別されています。

継続して更新する対象や、終了後にも正式な遷移がある対象には、終了状態を置かない場合があります。その場合は空欄にせず、該当なしと理由を記録します。終了状態から復帰させる必要があるなら、通常状態として扱うか、別の開始経路を設けるかを判断します。

表を作ってから図へ反映する

ISTQBは、状態遷移図と状態遷移表を同等のモデルとして説明しています。表では行に状態、列にイベントとガード条件、セルに遷移先状態とアクションを置きます(ISTQB CTFL v4.0.1 §4.2.4(PDF))。

この記事では、禁止と未決も確認できるように、表を先に作ります。図だけでは、矢印がない組み合わせが禁止なのか、まだ調べていないのかを区別できないためです。

  1. 対象に含める状態を列挙する
  2. 対象に届くイベントを列挙する
  3. 現在状態とイベントの組み合わせを作る
  4. 各組み合わせを許可、禁止、未決に分ける
  5. 許可した行へガード、遷移先、アクションを書く
  6. 禁止した行へ試行時の期待結果を書く
  7. 未決の行へ確認相手と期限を書く
  8. 許可した遷移を図へ反映する

図では、開始位置、状態、許可した遷移、必要な終了状態を示します。遷移のラベルはイベント [ガード条件] / アクションの順にすると、表と照合しやすくなります。このラベル形式はISTQBのシラバスでも紹介されており、存在しないガード条件やアクションは省略できます。

禁止と未決は、図を読みにくくするなら表だけに残せます。ただし、図にない行も表から削除しません。図と表の更新責任者を決め、許可した遷移、初期状態、終了状態が一致しているかを確認します。

状態遷移設計票を書く

以下はこの記事の編集上の空欄票であり、W3CやISTQBの公式様式ではありません。一つの機能または一つの管理対象につき一組を作ります。異なる責任者が判断する対象は分け、根拠がない項目は未決として確認先を残します。各記入票は一件分です。必要な件数だけ複製して使います。

1. 対象と責任範囲

項目 記入欄
対象名 (記入)
対象となる利用者・処理 (記入)
現行の処理・待ち・例外 (記入)
対象に含める処理 (記入)
対象に含めない処理 (記入)
現在状態の基準データ (記入)
状態を更新する責任者・処理 (記入)
関連する要件・受入条件 (記入)
業務判断の承認者 (記入)
組織レビューの要否・確認先 (記入)

2. 状態票

項目 記入欄
状態ID (記入)
状態名 (記入)
この状態と判断する条件 (記入)
判定に使う基準データ (記入)
この状態で守る条件 (記入)
初期状態か (記入)
終了状態か (記入)

初期状態を一つに確定できない場合は、開始経路と選択条件を遷移票へ追加します。終了状態がない場合は、該当なしと理由を対象票へ記録します。

3. イベント票

項目 記入欄
イベントID (記入)
イベント名 (記入)
発生元 (記入)
必要な入力 (記入)
入力の確認元 (記入)
実行を許可する役割 (記入)
重複・順序・再実行の扱い (記入)

複数の入口が同じイベントを発生させる場合は、認証、入力検証、重複対策を共通にできるかを確認します。入口ごとに異なるなら、その違いをイベント票かガード条件へ残します。

4. 遷移票

項目 記入欄
遷移ID (記入)
現在状態 (記入)
イベント (記入)
ガード条件 (記入)
ガードの確認元・時点・処理 (記入)
遷移区分 許可・禁止・未決
遷移先 (記入)
アクション (記入)
禁止時・失敗時の結果 (記入)
根拠 (記入)

許可では遷移先とアクションを、禁止では遷移先をなしとして試行時の結果を記入します。未決では根拠欄に確認相手と期限を記入し、結果を変える未決が残っている間は実装対象にしません。

5. 図との整合確認

確認項目 結果
初期状態が表と図で一致している (確認)
許可した全遷移が図にある (確認)
図にだけ存在する遷移がない (確認)
ガード条件とアクションが表を参照できる (確認)
必要な終了状態が一致している (確認)
禁止・未決の遷移票が残っている (確認)

6. 未決事項票

項目 記入欄
未決事項 (記入)
結果が変わる範囲 (記入)
確認相手 (記入)
期限 (記入)
解決後の更新先 (記入)

実装へ渡す

設計票をコードへ置き換える前に、各許可遷移の実装条件を決めます。

実装前に必要なのは、次の確認です。

  • 現在状態をどこから読み、どの基準データで判断するか
  • イベントの発生元をどこで認証し、入力をどこで検証するか
  • ガード条件をどのデータで、どの時点に、どの処理が確認するか
  • 状態変更とアクションをどの順序で行い、途中で失敗したときにどう整合させるか
  • 禁止した遷移を、画面だけでなく信頼できる処理側でも拒否するか

対象に応じて、次の項目も実装タスクへ含めます。

  • 同じイベントの重複、再試行、順序の入れ替わり
  • 同じ対象へ同時に遷移要求が届いた場合の採用結果
  • 状態変更、拒否、失敗の記録先と確認者
  • 複数の部品にまたがる責任、依存関係、入出力の約束

最後の項目は設計原則の選び方で整理できます。認可、一連の更新を途中状態にしない仕組み(トランザクション)、同時更新の実装方式は、利用する言語、データの保存先、外部サービスによって異なります。用語だけを設計票へ書いて完了にせず、実装タスクと確認方法へ分けます。

実装が設計票と異なる場合は、業務判断の承認者が要件変更か実装誤りかを判断します。設計担当者は設計票を、実装担当者はコードを、その判断へ合わせて更新します。

次工程では、設計票全体を一度に渡さず、一度に扱う遷移と対応するテスト範囲を説明できる単位へ分けます。具体的な手順はAIに渡す実装タスクの切り方で扱います。

テストへ渡す

ISTQBは、状態遷移図や表を基にするテストケースを、イベントの列と、それによる状態変更・アクションの列として表せると説明しています。また、全状態、全許可遷移、許可と禁止の両方を対象にする網羅基準を区別しています(ISTQB CTFL v4.0.1 §4.2.4(PDF))。

遷移票の現在状態をテストの開始状態、イベントとガード条件を実行条件、遷移先とアクションを期待結果へ移します。一つのテストケースにつき、次の票を一件作ります。

項目 記入欄
テストID (記入)
開始状態 (記入)
イベントと入力 (記入)
ガードの期待結果 成立・不成立・該当なし
期待する遷移区分 許可・禁止
期待する遷移先 (記入)
期待するアクション・応答 (記入)
確認する記録 (記入)

許可した遷移では、ガードが成立する場合と不成立の場合を分けます。禁止した遷移では、拒否時の応答、正式な状態、アクションの有無、記録を確認します。イベントを連続して実行する場合は、各手順後の状態を確認し、次のイベントの開始条件にします。

どの網羅基準を採用するかは、対象の重要度と既存のテスト方針で決めます。遷移をすべて通したという数値だけでは、入力の境界値、認可、障害時、性能などの品質は保証されません。状態遷移以外のテストを組み合わせる方法はテストの種類と選び方で確認できます。

AIで候補を出し、人が決める

要件、受入条件、既存コード、API仕様、データ定義から候補を整理するときは、AIへ次の形式で抽出を依頼できます。使用するモデル、与えた資料、入力できた範囲によって結果は変わり、網羅性や正確性は保証されません。最初の依頼ではコードを変更対象から外します。

対象: [対象名]
参照できる資料:
- [要件・受入条件]
- [コード・仕様の範囲]

1. 資料に明記された内容を、
   状態、イベント、ガード条件、遷移先、
   アクションに分け、参照箇所付きで列挙する
2. 明記されていない内容は補完せず、
   「未決」とする
3. 状態とイベントの全組み合わせを、
   許可・禁止・未決へ分ける
4. 既存コードと資料が一致しない箇所を
   別表にする
5. コードは変更しない

AIの表は候補です。業務とシステムに責任を持つ人が、次の内容を確認します。

  • 正式な現在状態を決める基準データ
  • イベントの発生元、入力の確認方法、実行を許可する役割
  • ガード条件の正しい判定元と評価時点
  • 禁止時と失敗時の応答、記録、通知
  • 重複、再試行、順序変更、同時更新の扱い
  • 実装とテストの合格条件

AIが参照していないコードや資料がある場合、その範囲への影響は判断できません。許可する遷移を根拠付きで説明できない状態は、コード変更へ進む前の停止条件です。生成後の確認手順はAI生成コードをレビューするで扱います。

次へ進める状態

次の項目を満たすと、状態遷移の設計を実装とテストへ渡せます。

  • 対象に含める処理、利用者、例外、対象外が決まっている
  • 各状態の判定条件、基準データ、初期状態が決まっている
  • 終了状態が必要かを判断し、不要なら理由がある
  • 状態とイベントの全組み合わせに、許可、禁止、未決が明記されている
  • 許可遷移のガード、遷移先、アクション、失敗時が決まっている
  • 禁止遷移の応答、正式な状態、記録が決まっている
  • 結果を変える未決事項が解決している
  • 表と図の許可遷移、初期状態、終了状態が一致している
  • 各遷移から実装タスクとテストケースを作れる

認可、重複、再試行、同時更新などを別タスクへ送る場合は、担当者、確認方法、期限を残します。図が整っていても、結果を変える未決や失敗時の扱いが残っていれば完了ではありません。

出典