アジャイルモデリング(AM)
公式サイト
モデリング成果物>UML 2 状態マシン図

UML 2 状態マシン図の概要

by Scott W. Ambler, Copyright 2003

 

オブジェクトは振る舞いと状態を持っています。つまり、ものごとを行い、ものごとを知っているわけです。オブジェクトの中には、他のオブジェクトと比べて、より多くの、あるいは少なくともより複雑なことを行ったり知っていたりするものがあります。途方もなく複雑なため、開発者がちょっとやそっとでは理解できないものもあります。複雑なクラス、特に自分の状態に応じて応答の仕方が異なるクラスをよく理解するには、UML状態マシン図(UML1.xではステートチャート図と呼ばれていたもの)を書いて、インスタンスがどう動くかを記述する必要があります。

UMLの状態マシン図では、オブジェクトが取りうるさまざまな状態と、その状態間の遷移を表します。実際、他のモデリング言語では、この種の図のことを状態遷移図と呼んだり、もっと簡単に状態図と呼ぶのが一般的です。状態とはオブジェクトの振る舞いパターン中の1つの段階を表すもので、UMLアクティビティ図と同じように、初期状態と最終状態が存在します。初期状態は生成状態とも呼ばれるもので、オブジェクトは最初に生成されたときにその状態に入ります。それに対して最終状態は、そこから出る遷移が存在しない状態です。遷移とはある状態から別の状態に進むことで、オブジェクトに対する内部的/外部的なイベントによって引き起こされます。

図1は、登録中のゼミクラスの状態マシン図の例です。角の丸い長方形が状態を表します。この図では、ゼミのインスタンスは「計画済」「スケジュール済」「登録中」「満員」「登録終了」という状態を取ることができます。オブジェクトはまず、黒丸で表された開始状態になり、最後には二重丸で表された終了状態になります。これは、UMLのアクティビティ図で使ったものと同じ表記法であり、UMLの一貫性を表すよい例になっています。

 

図1 登録中のゼミ

 

図1の矢印は、遷移、つまりある状態から別の状態への移行を表します。たとえば、ゼミが「スケジュール済」の状態にある場合、このゼミの登録を開始することもキャンセルすることもできます。遷移に付けるラベルの表記法は「イベント [ガード条件][/メソッドリスト]」という形式です。遷移を引き起こすイベントは、必ず記述しなければなりません。この図で言うと「登録を開始する」や「キャンセルされる」などです。ガード条件とは、真でなければ遷移が発生しない条件で、記述するかどうかは任意です。図では、「登録中」状態から「登録終了」状態への「学生が登録される」の遷移に、「[席が残っていない]」というガード条件が付いています。ガード条件の書き方は自由で、自由形式のテキストでも形式言語でもかまいません。私は、ホワイトボードでモデリングをしている場合には、誰にも読めるよう自由形式のテキストを使いますが、高機能なCASEツールを使っていて、そのツールが実際にその情報を処理して何か役に立つもの(実行可能なコードなど)を生成してくれる場合には、Javaなどのプログラミング言語やオブジェクト制約言語(OCL)などのモデリング言語を使用します。また、オブションで、「待ちリストに追加()」のようなメソッドの呼び出しを遷移に記述することができます。リスト内の順序は呼び出される順序と同じです。

状態はオブジェクトの属性値で表されます。たとえば、登録中のフラグが立っていて、まだ席が空いている場合、そのゼミは「登録中」の状態になります。状態内で呼び出されるメソッドを表すことも可能です。たとえば、「登録終了」の状態に入るときに「講師に通知()」メソッドが呼び出されます。状態の内部の表記法は、遷移の場合と同じですが、メソッドリストが必須でイベントが任意である点だけが異なります。たとえば「満員」状態では、学生が登録されるたびに、「待ちリストに追加()」および「ゼミ分割を考慮()」の操作が呼び出されます。イベントを書かなければ、オブジェクトがその状態にある間、そのメソッドは継続的に(ループで)呼び出されます。状態にある間に実行されるメソッドを私が記述するのは、メソッドが継続的に動いていることを示したい場合(情報を求めて他のオブジェクトにポーリングしているメソッドなど)や、重要なビジネス処理のロジックを実装しているメソッドの場合などです。オブジェクトが状態に入ったときに呼び出されるメソッドには「entry」というキーワードを付けます。図1の「登録中」や「登録終了」の状態を参照してください。オブジェクトが状態から出るときに呼び出されるメソッドには「exit」というキーワードを付けます。状態に入るときや出るときに呼び出されるメソッドを記述できると便利なのは、状態に入ったり出たりする遷移ごとに、同じメソッドを何度も書かないで済むからです。

メソッドが呼び出されて状態に重要な変化が起きると、遷移が発生します。メソッドが呼び出されると必ず遷移が起きるわけではないことを理解しておいてください。たとえば、getメソッドが呼び出されても遷移は発生しないでしょう。オブジェクトの状態が変わるわけではないからです(呼び出された時点で遅延されていた初期化が行われるのなら別ですが)。また、図1では、満員のゼミに学生を登録しようとしても学生がもう1人順番待ち名簿に追加されるだけでゼミ(オブジェクト)の状態は変わらないかもしれません。ただし、ゼミを分割することに決まった場合は別で、そのときにはゼミ(オブジェクト)の状態が変わります。遷移にはビジネスルールが反映されていることが分かります。たとえば、学生をコースに登録しようとすることができるのは、登録中の場合か、満員でしかも順番待ち名簿が長くなってゼミが(おそらく2つに)分割される可能性がある場合だけです。再帰遷移を書くこともできます。これは自己遷移とも呼ばれ、ある状態から出て同じ状態に戻る遷移です。ゼミが「満員」状態のときの「学生が辞める」の遷移がその例です。

慣習として、オブジェクトは必ずただ1つの状態にあると考えます。つまり、遷移は一瞬で完了するということです。もちろん私たちはこれが完全に正しくはないことを分かっていますが(どんなメソッドを実行するにもある程度時間がかかります)、遷移を完了するのに時間がかからないと考える方がずっと話は簡単になります。

ゼミのライフサイクルは非常に複雑で、図1に示されているのはその一部にすぎません。図2はライフサイクル全体を表したもので、図1は「登録」状態のサブ状態として書かれています。図2に詳細をすべて書くこともできたのですが、私はそうせずに図をシンプルにしておくことに決めました。AMの「モデルはシンプルに書こう」と「少しずつモデリングしよう」のプラクティスに従いたかったからです。実際のところ、私は図2のような図を作成するよりも、図3のような大雑把な図と図1のような詳細ビューとを使う方が気に入っています。その方が図が小さく理解しやすくなるからです。

 

図2 ゼミの完全なライフサイクル

 

 

図3 トップレベルの状態マシン図

 

図4は状態マシン図を少し違った視点から見たものです。これは、この状態にあるゼミに何が起きるかを関係者の視点から表現したものなので、分析レベルの図にずっと近いものになっています。この図は2つの並行したスイムレーンに区切られ、並列のサブ状態を表しています。サブ状態の1つはゼミを教える教授の視点から見たもの、もう1つはゼミの教材の更新を担当する講義助手の作業を表したものです。並行サブ状態はハードウェアの世界では一般的ですが、ビジネス分野のクラスではほとんど見られません。ですからこれはあまり意味のない例です。通常私はこの種の情報をUMLアクティビティ図またはUMLタイミング図を使って記述するのですが、ここではこのような表記法もあるということを見せるための例が必要だったのです。

 

図4 「受講中」状態

 

図4には遷移の記述方法がいくつか示されています。「受講中」状態から出る「休暇開始」の遷移はすべてのサブ状態に適用されます。この遷移は1つのサブ状態ではなくスーパー状態から出ているからです。「課題が提出される」の遷移は、さまざまなところから発生します。これはスーパー状態の外枠に結び付いていることから分かります。それに対して「休暇が終わる」の遷移元は「休暇」状態であることが明示的に定義されています。この状態に入る最初の遷移は「学期が始まる」であることが、初期状態のシンボルによって示されています。この状態は「登録」状態から来るようにモデリングすることも可能です(どちらの方法でも問題ありません)。

「学期が始まる」と「休暇終了」の遷移は、まずマージされ、次にフォークに入って、並行サブ状態のいずれかに移ります。Hを丸で囲んだ履歴擬似状態によって、ゼミが以前にこの状態にあり、いったんそこから出て戻ってきた場合には、もとのサブ状態に戻ることが示されています。履歴擬似状態から出る矢印は、ゼミが「受講中」のスーパー状態に最初に入ったときのデフォルトのサブ状態が「コース教材を配る」であることを示しています。

 

状態マシン図の書き方

状態マシン図を書くときには、まず生成状態を明らかにし、終了状態があるかどうかを確認します。その後、オブジェクトがそれ以外にどのような状態(生存期間における段階)を通るかを考えます。属性の境界値を調べると状態が見つかることもよくあります。たとえば、ゼミの学生数が最大値に達したら、ゼミは満員になります。「満員」が正当な状態である根拠は、学生が登録しようとすると順番待ち名簿に載せられる、ゼミが2つに分割する候補になるなど、適用されるルールが違ってくることです。

できる限り多くの状態を書き出したら、次は遷移を探します。状態ごとに、オブジェクトがそこから出ることができるならその方法を考えます。それによって遷移が見つかります。すべての遷移は状態から状態へと移るものなので、その遷移によってどの新しい状態に移るかを考えます(同じ状態に戻ってくる再帰遷移を忘れないでください)。また、クラス図で識別したメソッドも見てください。そのいくつかは、状態マシン図の遷移に対応します。

状態マシンのモデリング時にエラー状況が見つかることはよくあります。「オブジェクトがこの状態にあるときにこの遷移が起きることは許されるのだろうか」と常に考えることになるからです。答えがYESであれば図に遷移を追加します。答えがNOなら、それを起きる可能性のある問題として文書化し、遷移が発生することのないようプログラムに適切なエラーチェックコードを追加できるようにします。

状態マシン図を継承できるといいのですが、その可能性はきわめて低いでしょう。「サブクラスはスーパークラスと似ているけれども、それでもどこか異なる」というのが継承の定義だからです。サブクラスの振る舞いは、通常はスーパークラスの振る舞いと異なります。つまり、状態マシン図を持つクラスを継承する場合には、状態マシン図を見直さなければならないということです。1つだけよい点は、状態や遷移の多くを再利用できることです。おそらく、新しい状態や遷移を追加するか、いくつかを定義し直せばよいでしょう。

 

アジャイルさを保つ

状態マシンのモデリングは、動的モデリングの手法であり、システム内の振る舞い(この場合はある1つのクラスのインスタンスに固有の振る舞い)を明らかにすることが目的です。私は、クラスがその状態によって異なる振る舞いを示すときに、状態マシン図を作成することにしています。たとえば、「住所」クラスは非常に単純であり、システムで表示し操作するデータを表しているだけです。それに対して「ゼミ」クラスはきわめて複雑なので、状態マシン図を作成することには意義があります。

ビジネスアプリケーションでは、状態マシン図を作成する必要があるほど複雑なクラスはほんの少し、せいぜい5%程度でしょう。ただし、リアルタイムシステムの世界では、状態マシン図はずっとよく使われています(Douglass 1999)。

 

 

注: この成果物の説明は『The Object Primer 3rd Edition: Agile Modeling Driven Development with UML 2』より抜粋しました。本ではより詳しく説明しています。


推奨文献

Agile Modeling

 

その他の文献

アジャイルモデリング(AM)について詳しく知るにはこの本をお薦めします。

 アジャイルモデリング

 

Let Us Help (以下、北米での話ですのでご注意ください)

Ronin International, Inc. continues to help numerous organizations to learn about and hopefully adopt agile techniques and philosophies.  We offer both consulting and training offerings.  In addition we host several sites - Agile Modeling, Agile Database Techniques, UML Modeling Style Guidelines, Enterprise Unified Process (EUP) - that you may find of value.

You might find several of my books to be of interest, including The Object Primer, Agile Modeling, The Elements of UML Style, and Agile Database Techniques.

For more information please contact Michael Vizdos at 866-AT-RONIN (U.S. number) or via e-mail (michael.vizdos@ronin-intl.com).

 

visits since June 8, 2004.