複雑なソフトウェアシステムのアーキテクチャにおいて、制御フローは極めて重要です。イベント、シーケンス、または入力に反応するシステムを設計する際、状態機械図は、設計図を提供します。これらの図は、オブジェクトやシステムの時間的な挙動をモデル化します。システムが刺激に応じて状態間をどのように遷移するかを定義するために不可欠です。
機械が状態を変化させるという概念は直感的ですが、モデルによってその数学的・論理的な基盤は大きく異なります。特に、有限状態機械(FSM), ムーア型機械、およびメーリー型機械は、出力がどのように生成されるか、およびシステムが外部入力に対してどれほど反応的であるかを決定します。このガイドでは、UML(統合モデル言語)の文脈の中でこれらのモデルを詳細に分析し、構造、挙動、実用的応用について深く掘り下げます。

有限状態機械(FSM)の理解 🧱
この議論の中心には有限状態機械があります。FSMは、コンピュータプログラムや順序論理回路を設計するために使用される計算モデルです。任意の時点で有限個の状態のうちの一つにしか存在できません。
FSMの核心的な構成要素
- 状態:システムが取りうる明確な状態または構成(例:アイドル, アクティブ, エラー).
- 遷移:特定のイベントによって引き起こされる、一つの状態から別の状態への移動。
- 初期状態:システムライフサイクルの出発点。
- 最終状態:プロセスの終了点。
- イベント:遷移を引き起こす入力。
UMLでは、FSMはしばしば状態機械図として可視化される。これらの図は、クラスやシステムの動的振る舞いを捉えている。それらは、シーケンス図やアクティビティ図とは異なり、単一のオブジェクトの状態のライフサイクルにのみ焦点を当てるため、特徴が異なる。
なぜFSMを使うのか?
- 明確さ: コードだけでは難しく追いかけることが多い論理の視覚的マップを提供する。
- デバッグ: システムがループや予期しない状態に閉じ込められた場合、図は欠落している遷移を強調する。
- 一貫性: 状態依存の論理がアプリケーション全体に一貫して適用されることを保証する。
ムーア機械:出力は状態のみに基づく 🟦
ムーア機械は、出力が状態に依存する特定の有限状態機械の一種である。唯一現在の状態にのみ依存する。つまり、入力が変化しても出力は即座に変化せず、状態遷移が完了するまで待つ必要がある。
ムーア論理
数学的に、出力関数は次のように定義される:
出力 = f(現在の状態)
ムーアモデルでは、出力はノード(状態)自体に関連付けられる。システムが状態に入ると、その状態に対応する出力が即座に有効化される。システムがその状態を離れるまで、出力は安定したまま維持される。
ムーア機械の利点
- 安定性: 出力は状態変化と同期される。遷移中に入力の変動が原因でゴーストが発生することはない。
- 単純さ: 出力が状態の期間中固定されるため、論理がしばしばより簡単に理解できる。
- クロック同期: ハードウェアの文脈では、出力はしばしばクロックエッジでサンプリングされるため、ムーア機械は自然に同期的になる。
ムーア機械の欠点
- 遅延: 出力が状態変化を待つため、入力イベントと出力応答の間に遅延が生じる。
- より多くの状態: メーリー機械と同じ動作を達成するためには、ムーア機械は、遷移論理で処理されるはずの入力を区別するために、より多くの状態を必要とする場合がある。
例のシナリオ:信号機コントローラ
- 状態:赤 ➡️ 出力:停止
- 状態:緑 ➡️ 出力:進行
- 状態:黄 ➡️ 出力:注意
ここでは、出力はライトの色に内在しています。タイマー入力がわずかに変化しても、出力はサイクルが完了するまで表示されている色に結びついたままです。
メーリー機械:状態と入力に基づく出力 🟥
メーリー機械は、出力が両方の要素に依存する、別の種類の有限状態機械です現在の状態および現在の入力。これにより、状態の変化がなくても入力と非同期に変化する出力を持つ、より反応性の高いシステムが作られます。
メーリー論理
数学的には、出力関数は次のように定義されます:
出力 = f(現在の状態、現在の入力)
メーリーモデルでは、出力はノードではなく遷移(矢印)に関連付けられます。これにより、同じ状態でも遷移を引き起こした要因によって異なる出力を生成できるようになります。
メーリー機械の利点
- 反応性:入力を受けると即座に出力が変化するため、レイテンシが低下します。
- 効率性:入力の変化を遷移内で処理できるため、同じ論理を実装するのにムーア機械よりも少ない状態数で済むことが多いです。
- 柔軟性:入力イベントに対して出力タイミングをより細かく制御できるようになります。
メーリー機械の欠点
- ギャップ:出力は入力に依存するため、入力信号がノイズを含んでいたり、遷移中に変化した場合、出力がちらついたり予測不能な動作を示す可能性があります。
- 複雑性: 論理は遷移に分散されており、モア状態と比較して図をよりごちゃごちゃにすることがあります。
- 同期: ハードウェアでは、ミーリー機械は非同期になりやすく、グローバルクロックと同期させるのが難しいことがあります。
例のシナリオ:自動販売機の釣り銭
- 状態:アイドル + 入力:1ドル硬貨 ➡️ 出力:1ドルのクレジット
- 状態:アイドル + 入力:5ドル硬貨 ➡️ 出力:5ドルのクレジット
この場合、状態は同じ(アイドル)ですが、出力は入力によって異なります。モア機械では、この違いを表すために「アイドル-クレジット1」と「アイドル-クレジット5」という別々の状態が必要になります。
モア対ミーリー:詳細な比較 📊
構造的および論理的な違いを可視化するため、以下の分解を検討してください。
| 特徴 | モア機械 | ミーリー機械 |
|---|---|---|
| 出力の依存関係 | 現在の状態のみ | 現在の状態+入力 |
| 出力の位置 | 状態ノード内部 | 遷移矢印上 |
| 遅延 | 高い(状態変更が必要) | 低い(即応応答) |
| 状態数 | 多くの状態が必要になることが多い | 少ない状態で済むことが多い |
| グリッチリスク | 低い(同期的) | 高い(非同期入力) |
| 設計の複雑さ | 単純な論理マッピング | より複雑な遷移論理 |
UML状態機械図:標準 📐
統一モデリング言語(UML)は、状態機械を表現するための標準化された記法を提供する。モアとミーリの理論的モデルはデジタル論理に存在するが、UMLはこれらの概念をソフトウェア工学のニーズに合わせて抽象化している。UML状態機械図は多目的であり、アクションとトリガーの定義の仕方によって、どちらのモデルも表現できる。
UMLの主要な記法
- 状態:丸みを帯びた長方形で表される。状態名と、エントリーアクション/エグジットアクションのオプション領域を含む。
- 遷移:2つの状態をつなぐ矢印。トリガー、ガード条件、およびアクションを含むことがある。
- 初期状態:実線の黒丸。
- 最終状態:輪を囲んだ実線の黒丸。
- 接続点:複数の遷移をマージまたは分割するために使用される小さな円。
- 履歴状態:内部に’H’がある円で、状態機械が中断された場合にどこから再開すべきかを示す。
モアとミーリをUMLにマッピングする
UMLは、一方のモデルを他方よりも厳密に強制するものではない。代わりに、アーキテクトが望ましい動作に基づいて選択できるようにしている。
- UMLにおけるモアの実装: 出力アクションを状態ボックスの Entry または Exit セクションに定義する。これにより、遷移のトリガーに関係なく、状態に入力されたときに出力が発生することが保証される。
- UMLにおけるミーリの実装: 遷移ライン自体に出力アクションを定義する(トリガー/アクション構文のアクション部分)。これにより、入力に依存して遷移が発火したときに出力が発生することが保証される。
設計上の考慮事項とベストプラクティス 🛠️
モデルの選択は、システムの保守性とパフォーマンスに影響を与える。設計段階で考慮すべき重要な要因を以下に示す。
1. タイミングおよびレイテンシ要件
システムがユーザー入力に対して即時フィードバックを必要とする場合(例:ゲームコントローラーやリアルタイムセンサー)、ミーリアプローチはしばしば優れている。システムが安定したクロック出力(例:ディスプレイドライバーや安全連動装置)を必要とする場合、モアアプローチはより安全である。
2. 複雑さの管理
システムが拡大するにつれて、状態数が急増する可能性がある。同等の機能に対して、モアマシンはより多くの状態を必要とする傾向がある。状態数が制約となる場合(組み込みシステムでは一般的)は、ミーリマシンの方が効率的である可能性がある。しかし、モアマシンは動作が状態コンテナ内にカプセル化されているため、人間にとって読みやすいことが多い。
3. 入力ノイズと安定性
入力信号が不安定な環境では、ミーリマシンは不安定な出力を生成する可能性がある。モアマシンは出力を入力信号から分離し、遷移期間中にノイズをフィルタリングする。重要な安全システムでは、モア論理が一般的に好まれる。
4. テストと検証
- モア: 状態カバレッジのテストが容易。状態の出力を独立して検証できる。
- ミーリ: 状態と入力の組み合わせをテストする必要がある。これによりテストマトリクスが著しく増加する。
一般的な実装上の落とし穴 ⚠️
明確な図があっても、実装段階で誤りが発生することが多い。これらの落とし穴を理解することで、状態機械が意図した通りに動作することを保証できる。
1. 欠落した遷移
よくある誤りは、特定の状態で入力に対する動作を定義しないことである。システムが処理できないイベントを受け取った場合、クラッシュするか、定義されていない状態に入ってしまう可能性がある。常にすべての状態に定義された応答、またはデフォルトのエラーハンドラーが存在することを確認する。
2. 循環依存
遷移が、終端状態または待機状態に到達できない無限ループを作らないようにしてください。無限ループはCPUの過負荷やユーザーインターフェースのフリーズを引き起こす可能性があります。
3. 状態爆発
あまりにも多くの変数を状態定義に組み込むと、組み合わせ的爆発が発生する可能性があります。使用するべきは複合状態UMLで関連する状態をまとめるために使用します。これにより、図の管理が容易になり、トップレベルの状態の総数を減らすことができます。
4. 非同期イベントの無視
ソフトウェアでは、イベントがしばしば非同期に到着します。状態機械がクロックと同期された入力(ムーア型)を期待しているのに、非同期に到着した入力(メーリー型)を受け取ると、レースコンディションが発生する可能性があります。コードの実行モデルが図の論理モデルと一致していることを確認してください。
高度な概念:複合状態と並列状態 🧩
UML状態機械図は、基本的なFSM理論を越えた機能をサポートしており、より複雑なシステムモデル化を可能にしています。
複合状態
複合状態は他の状態を含みます。これは階層的モデル化に有用です。たとえば、デバイス状態には、オンおよびオフのようなサブ状態を含むことがあります。遷移は複合状態から脱出せずに内部で発生することができ、または複合状態全体が別の高レベル状態に遷移することもできます。
並列状態(直交領域)
UMLでは、状態機械が複数の独立した領域を同時に実行できるようにしています。たとえば、電話オブジェクトには通話領域と着信音領域を持つことがあります。これらの領域は並行して動作し、システムが単一の状態オブジェクト内で複数の論理プロセスを処理できるようにします。
現実世界の応用シナリオ 🌍
状態機械は現代のコンピューティングにおいて広く利用されています。以下に、異なる分野への適用例を示します。
1. ネットワークプロトコル
TCPのようなプロトコルは状態機械に大きく依存しています。接続は、閉じられた, リッスン, 確立された、そしてクローズウェイト。システムの動作は、接続がどの状態にあるかによってまったく変わる。
2. ユーザーインターフェース(UI)フロー
Webフォーム、ウィザード、ログイン画面は、古典的な状態機械の応用例である。ユーザーは、フィールドが有効(状態条件)になるまで、フォームを送信できない(遷移)。検証に失敗した場合、システムは検証エラー状態のままになる。
3. ゲーム開発
キャラクターの行動は、しばしば状態機械を使ってモデル化される。敵はパトロール, 追跡、または攻撃の状態にあるかもしれない。パトロールへ追跡への遷移は、プレイヤーの検出(入力)に依存する。
4. ワークフロー自動化
ビジネスプロセス管理システムは、文書承認を追跡するために状態機械を使用する。文書は下書きへレビューへ承認済み各状態には、特定の権限と利用可能な操作があります。
モデル間の切り替え 🔄
場合によっては、システムがメーリー機械として始まり、後にムーア機械へと進化するか、その逆も起こります。これは通常、リファクタリング中や要件が変更された際に発生します。
メーリーからムーアへの変換
メーリー機械をムーア機械に変換するには、状態を分割する必要があります。同じ入力に対して異なる出力を持つ2つの出力遷移がある状態の場合、これらの動作を分離するために新しい状態を作成します。これにより、出力が状態にのみ依存することを保証します。
ムーアからメーリーへの変換
ムーアからメーリーへの変換は一般的に簡単です。出力アクションを状態のエントリから入力遷移に移動できます。ただし、これにより入力と出力の結合が強くなり、適切に管理されない場合、再び遅延問題が発生する可能性があります。
モデル選択に関する最終的な考察 🎯
有限状態機械、ムーア、メーリーのモデルのうちどれを選ぶかは、「最良」の選択を見つけることではなく、プロジェクトの制約に最も適したものを選ぶことである。ムーア機械は論理マッピングにおいて安定性と単純さを提供し、安全が重要なシステムや表示が重いシステムに適している。一方、メーリー機械は速度と効率を提供し、入力が多く、遅延に敏感なアプリケーションに適している。
UMLは、これらの選択を明確に可視化するためのキャンバスを提供する。図を正しく使い、一般的な落とし穴を避けることで、堅牢でテスト可能かつ保守可能なシステムを構築できる。重要なのは、状態機械が単なる図ではなく、システムの論理とその環境との契約であるということを理解することである。
よくある質問(FAQ) ❓
ムーアとメーリーの主な違いは何ですか?
ムーアの出力は現在の状態にのみ依存する。メーリーの出力は現在の状態と現在の入力の両方に依存する。
どちらのモデルが速いですか?
メーリー機械は一般的に速い。出力は状態遷移を待たずに、入力と同時に即座に変化できるからである。
1つの図でムーアとメーリーの論理を混在させることは可能ですか?
はい、UMLでは可能です。一部の状態をムーアのように(エントリ時に出力)、遷移をメーリーのように(トリガー時に出力)動作させることができます。ただし、保守性を高めるために一貫性を保つことを推奨します。
状態機械はソフトウェアで動作しますか?
まったく問題ありません。デジタル論理から生まれたものの、状態機械は複雑な制御フローを管理するためのソフトウェア工学における基本的な設計パターンです。
状態に外出遷移がない場合はどうなりますか?
システムはデッドロック状態または終端状態に達します。デフォルトのエラーハンドラーやグローバルリセット機構が実装されていない限り、無限に待機し続けます。











