より良いシステム開発のために、状態遷移設計のことを知ってほしい

# 状態遷移による設計を行う意義

状態遷移を使った分析・設計というと主に組み込み開発向けの内容だったりします。
でもそんなことは無いですね。ゲーム開発や画面遷移といった開発にも適用されます。自分ではビジネスモデルのワークフローでも適用したことがあります。

自分が感じている状態遷移のメリットは、

* 分析段階から状態遷移図を使ってモデリングしておくと早い段階で仕様モレや無理な遷移を見つけて見直すことができます。
* プロジェクトメンバーとの意思合わせがし易いです。
* 状態遷移に絡む不具合が発生しても、あーここの遷移がダメだよねと直ぐに対処できます。
* 状態遷移モデルが出来上がれば、そのまま実装するだけです。
* 状態数が十数個くらいの状態遷移モデルだと滅多に不具合を出したことがありません。それだけ品質の良い状態を保つことが出来るので、自信が付きます。
* ワークフローの仕様が変わったとか、クリティカルな処理で状態遷移を見直すことはあります。でもその見直しも大した時間を要さずに対応することが出来ます。状態遷移のない設計のときは死ぬ思いで対応していましたから大違いです。

デメリットは、

* 状態遷移設計に触れたことがないメンバーの教育が必要です。
* 状態遷移に正解が無いこともあります。状態遷移を使ってそんな事ありえるの？という意見もあるかも知れませんが、人によって切り口が違ったり、あまりにクリティカルな状態遷移だと悩むんです。
* 状態遷移図と状態遷移表の相互変換や、コードの自動生成が欲しくなると有料ツールを使わざるを得ない。

# 状態遷移図のキホン

状態遷移図は、有限オートマトンかUMLのステートマシンを用います。
有限オートマトンについては [Wikipedia](https://ja.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E3%82%AA%E3%83%BC%E3%83%88%E3%83%9E%E3%83%88%E3%83%B3) などを参考にしてください。ここではUMLのステートマシンについて書きます。

以下は基本的な表記です。
状態遷移設計における注意点はまた後で記すこととして、まずは図の説明です。

![state1.png](https://qiita-image-store.s3.amazonaws.com/0/114529/55fc34ba-8151-270f-56e6-7bd8af8ae20d.png)

* 状態には相応しい状態名を定義します。
* 状態には入場、退場、繰り返して実行するアクティビティを定義できます。
* 状態には自己遷移というトリガーも持てます。このときは退場→入場のアクティビティが実行されます。
* 状態には自己遷移とは別に、単にトリガーによって実行されるアクティビティも定義できます。
* 状態は階層的に状態を配置することが出来ます。これをコンポジット状態といいます。
* 状態には点線を引くことで直交状態を定義できます。並行同時に動作する遷移ですね。
* イベントにも相応しいイベント名を定義します。
* イベントには遷移条件やイベントが発火したときに行うアクティビティを定義できます。
* コンポジット状態から出て戻るときに状態履歴を定義することで、以前のコンポジット内の状態に戻ることが出来ます。
* 浅い状態履歴と深い状態履歴があり、コンポジット状態がいくつも階層がある場合、深い状態履歴の場合はその内部の状態履歴も維持されます。

ちょっと駆け足でした。
他にもフォーク／ジョインで並列状態を定義したり、ChoiceとJunctionではガード条件と遷移アクションの評価/実行順序が違うんだよとか、テンプレート的な状態遷移図を元に特化して状態を作ったり出来るんだよとかあります。好んで使おうとしませんけど。

# 状態遷移表を使った設計をしよう

状態遷移図は視覚的に理解できますが、ある状態でこのトリガを受け取った時のパターンがモレてました～という時がよくあります。全ての状態とトリガの組み合わせを確認するには状態遷移表を使うことです。
わたしはもともとZIPCを使ったことがあるので「拡張階層化状態遷移表」という形式を使います。ツール自体はもう使っていませんが、エクセルなどで状態遷移表を作成しています。ついでにマクロでコードを自動生成してきました。

![state2.png](https://qiita-image-store.s3.amazonaws.com/0/114529/0ccabf6f-9a85-22d7-1d73-a79756ba2afa.png)

がんばって解説しようかと思いましたけど、なかなか大変なので、こちらの記事をお読みください。m(_ _)m
表の中で条件分岐やアクションの定義、ある遷移の中でありえないトリガーが来た時に不可や無視といった定義が出来るのがポイントです。

「状態遷移表を使用した設計モデル（拡張階層化状態遷移表）」
http://monoist.atmarkit.co.jp/mn/articles/1209/24/news004.html

# 状態遷移図と状態遷移表は両方ともメンテナンスしよう

状態遷移図と状態遷移表はセットで使います。両方のメンテナンスが必要ですが、それだけをメリットがあります。

# 状態遷移の知識体系っぽいこと

状態遷移図や状態遷移表の書き方を知ったところで、いきなり状態遷移設計ができる人なんて居ません。PMBOKやBABOKと同じように、状態遷移設計知識体系（Statement Transition Engineering Book Of Knowledge）が必要ですね。いまのところこういう名前のBOKは存在しませんけど。(^ ^);

まず大事なのは、いきなり状態遷移設計しないこと！
適切な要求分析からユースケース分析を行い、システム化の範囲を決めてから取り掛かかりましょう。ちゃんとブレイクダウンすることで状態遷移設計に繋げることが出来るのです。この辺りはモデル駆動開発の体系が役立ちますかね。

状態遷移というと、センサー状態遷移や画面状態遷移といった個別に作成するイメージがある方もみえるかと。そういう状態遷移も作成しますが、威力を発揮するのはシステム全体の状態遷移です。
ユースケース分析すると複数のユースケースが出来上がります。でもユースケース別にシステムが別れるわけではありません。やっぱりシステムは一つなので、システム全体の振る舞いを決めなければなりません。ある状態ではこのユースケースが実行できるけど、別のユースケースは実行できないといった定義ですね。状態遷移設計はシステム全体の世界地図になり得ます。

状態遷移設計で、状態をたくさん作りすぎて状態爆発したり、ある一点の状態から放射状に行って戻ってくるだけの状態遷移を作ってしまう場合は、一度上流の分析や設計に戻ったほうが良いです。意味のある状態抽出には上流の観点が必要です。システム全体の状態遷移はユーザー観点で抽出すべきだからです。利用者の行動をトリガーとして受けた時に、システムはどういった振る舞いをすべきかを定義するからです。ライフサイクルを把握するために作成しましょう。

状態遷移図とアクティビティ図は別物です。アクティビティ図は順序性のある活動を表現するための図で流れ図と同等です。状態遷移図を書いているつもりでいつの間にかアクティビティ図になっている人は自動遷移するような図を書いています。そういう時は帽子をかぶり直してアクティビティ図を書きましょう。それはある状態もしくはトリガーで実行されるアクティビティになりますね。

最後に、状態遷移設計は一人でしないこと。
プロジェクトメンバーや必要であればユーザーサイドも巻き込むことです。
一人で設計していては気付かないことが多々あります。複数人でとりかかれば、いろいろな事が見えてきます。作っている最中から意思疎通できると楽ですよね。