Processingで学ぶ 実践的プログラミング専門課程

第20回UML(3) シーケンス図⁠ステートチャート図

導入

プログラミングを学び始めた人が最初に習う図法は、ほぼ間違いなくフローチャートです。アルゴリズムを記述する方法として大変優れており、きちんと身に付けるべき課題です。ところが、いざ実際にGUIアプリケーションを作成しようとすると、困ってしまいます。GUIアプリケーションの動きはフローチャートだけではどうも表現しにくいのです。そこで考案されたのがシーケンス図や状態遷移図(ステートチャート図)です。これらの図法を習得すると、一気にGUIアプリケーションの動きを図にすることが楽になります。まさに視野が開ける、あるいはレベルアップした、そんな感覚を味わうことでしょう。

展開

シーケンス図とは

シーケンス図と、それに関連する語句の定義を示します。

  • シーケンス図:複数のオブジェクトの生死を縦の平行線で示し、相互作用を水平の矢印で示した図。
  • オブジェクト:ここでのオブジェクトとは、主にソフトウェア実行時に生成されたクラスの実体のこと。
シーケンス図の例
画像

上部のスティックマンや矩形がオブジェクトを表します。オブジェクトから下に伸びる線がオブジェクトの生死を時系列で表すためのものです。破線の時はオブジェクトが生成されていない、あるいはオブジェクトが生成されていても何らかの処理が実行されていない状態です。幅のある帯状になったときに生成されている、あるいは何らかの処理が実行されていることを表します。オブジェクトが破棄された場合は破線あるいは帯の終端に×をつけます。

例えばオブジェクトAはソフトウェアの実行中ずっと存在するオブジェクトです。実行しているソフトウェアそのものであるときもあります。オブジェクトBはAが生成したオブジェクトです。オブジェクトCはBによって生成され、CのメソッドC1がBから呼ばれている様子を図示しています。

UMLの規定では、オブジェクトが生きていない時点の垂直線や、オブジェクト間でメソッドを呼んだ後、制御が呼び出し元に戻る際の矢印の線は破線で表すことになっています。

細かく言えば、同期処理を呼び出す場合の矢印は塗りつぶした矢印(─⁠──▶⁠⁠、非同期処理を呼び出す場合は開いた矢印(─⁠──>⁠⁠、戻りの矢印は常に破線で開いた矢印(<─ ─ ─)などと規定されています。ですが、フリーハンドで紙の上に書く図で几帳面にこれらのルールを遵守する必要はありません。必要ならば守る程度で良いでしょう。

  • 同期処理:命令Aが実行されると、Aの実行が完了するまで次の命令Bを実行しないような仕組み。
  • 非同期処理:命令Aの実行が開始した後、Aの完了を待たずに次の命令Bが実行できるような仕組み。

先ほどの例では、BはAから生成された後、自律的に動作し、Cを生成しCのメソッドC1を呼び出しています。C1は同期メソッドで、終了後Bに処理を戻します。そしてオブジェクトBはメソッドB1を実行して、一応仕事を終えます。

Bが仕事をしている間、AはA1A2というメソッドを実行しています。その後ユーザからメソッドA3を実行する要請を受けてA3を実行しました。メソッドA1A2A3はオブジェクトBやCに対して非同期のメソッドであると言えます。

以上がこのシーケンス図の表現した動作です。

sketchをシーケンス図で表現する

次のskecthをシーケンス図で表現してみます。

ExSequenceDiagram.pde
ArrayList<Bubble> a = new ArrayList();

void setup(){
  background(0);
}

void draw(){
  background(0);
  Bubble b = new Bubble();
  a.add(b);
  for(Bubble o : a){
   o.show();
  } 
  delay(500);
  if (a.size() > 2) a.remove(0);
}
Bubble.pde
class Bubble{
  int x;
  int y;
  int r;
  
  public Bubble(){
    x = (int) random(100);
    y = (int) random(100);
    r = (int) random(20);
  }

  public void show(){
    ellipse(x,y,r,r);
  }
}
ExSequenceDiagramのシーケンス図
画像

かなり大まかに描いたシーケンス図ですが、sketchに登場する各クラスのオブジェクトが俯瞰でき、生き死にの様子も見て取れます。⁠ArrayListの要素数が2より大きいとオブジェクトを削除する」というロジックなのに、実際には一度に表示される円の数がどうして3つなのか、こうして実行の流れを追ってみると納得できることでしょう。この動作をフローチャートで描くと結構厄介です。シーケンス図は「ざっくり描く」ことに大変適しています。

ステートチャート図(状態遷移図)とは

ステートチャート図と、それに関連する語句の定義を示します。

  • ステートチャート図:外部からか、内部からかのアクションによって、システムの状態が変化するさまを図示します。
ステートチャート図の例
画像

このステートチャート図では、CADシステムの状態遷移を表現しています。起動直後は閲覧モード。切り替え操作によって作図モードとなり、また切り替え操作によって閲覧モードに戻ります。ソフトウェアの終了は、どちらのモードからでも可能になっています。左上部にある●(黒丸)が状態遷移の始まりを表す記号です。開始状態と呼びます。右側にある⦿(丸中黒)が状態遷移の終了を表す記号です。終了状態と呼びます。場合によっては終了状態は図示されません。無限ループで動き続けるシステムがその例です。

このステートチャート図をsketchにしてみます。

ExStateChartDiagram.pde
boolean isDrawMode = false;
color ViewModeColor = color(0,255,0);
color DrawModeColor = color(255,255,255);
color CurrentModeColor = ViewModeColor;

void setup(){
  background(CurrentModeColor);
}

void draw(){
  background(CurrentModeColor);
}

void mouseClicked() {
  if (isDrawMode == false) {
    isDrawMode = true;
    CurrentModeColor = DrawModeColor;
  } else {
    isDrawMode = false;
    CurrentModeColor = ViewModeColor;
  }
}

void keyPressed() {
  if (keyCode == 'q' || keyCode == 'Q') {
    exit();
  } 
}

sketchExStateChartDiagram.pdeを実行すると、緑色のディスプレイウインドウが表示されます。これが「閲覧モード」状態とします。ディスプレイウインドウ上でマウスボタンがクリックされると、⁠作図モード」状態に切り替わります。作図モードではディスプレイウインドウの色を白にします。以後、マウスボタンがクリックされるごとに状態が変更されます。どちらのモード状態でも、アルファベットのqまたはQのキーが押下されるとsketchが終了します。確かにステートチャート図通りの動きをしています。これだけの動作なら、フローチャートで表現することも難しくなさそうです。しかし、drawメソッドのフローチャート、mouseClickedメソッドのフローチャート、keyPressedメソッドのフローチャートと……、メソッドの数だけフローチャートが必要です。そして、それらのチャートはどこで関連しあうのかを記述する手段がありません。しいて可能なことと言えば、それぞれのフローチャートを横に並べ、実行のタイミングを揃えることでしょう。それはすなわちシーケンス図です。ステートチャート図はシーケンス図を更にメタな領域から眺めて抽象化したものなのです。

UML活用の手引き

UMLの各図はどのように活用すれば良いでしょうか。唯一絶対のメソッドはありませんが、私は次のような手順をお勧めします。

  1. 作成したいアプリケーションのイメージを文章にする。あるいは、作成済みのアプリケーションについて、こう動いてほしいという要求を文章にする。
  2. 文章を元に、ユースケース図を作成する。
  3. ユースケース図を元に、クラス名のみのクラス図と、おおまかなシーケンス図を作成する。状態変化のあるアプリケーションで必要ならステートチャート図も作成する。
  4. 3.の成果物を元にプロトタイプを作成する。つまり、具体的なコードを記述し、実行してみる。作成済みのコードがあれば、意図しない動きの部分を探して、成果物に照らし合わせて目的の動作に近づくよう変更する。
  5. 4.で判明した不都合や課題を整理する。
  6. 2.や3.に戻る。

この作業を繰り返すことで、次第にプロトタイプのコードが完成形のアプリケーションに近づいていくのです。開発のスパイラルが上昇して行くうちに、2.や3.の図が詳細度と具体性を増していきます。

必要ならば、3.や4.の段階で、アルゴリズムが複雑なメソッドについてはフローチャートを描くことが有効です。しかし、フローチャートを描かなければ理解できないようなアルゴリズムであれば、そもそもそのアルゴリズムに問題があるのかもしれません。優れたアルゴリズムはシンプルで分かりやすいものですから。

だたし、UMLの各図を描くことにあまり執着しすぎないようにしてください。結局必要なのはコードそのものです。コードが最も正しくそのアプリケーションを表現するものです。図の維持管理を大事にし過ぎて、コーディングがおろそかになってしまうようでは本末転倒です。

UMLを活用しよう

これまで3回にわたってUMLを学習しました。UMLの便利さを実感し、活用を始められましたでしょうか。UMLは単なる図法でそれ自体が動くコードになるわけではありませんが、自分の考えを整理し、また人に伝える強力なツールです。ぜひとも活用を開始してください。

演習

演習1(難易度:middle)

連載第2回に掲載したsketch Bounce.pdeの動作ををシーケンス図で表現しましょう。実行しているsketch Bounce.pdeと、ディスプレイウインドウをそれぞれオブジェクトと考え、オブジェクト間のメッセージのやり取りを記述してください。

演習2(難易度:middle)

次のステートチャート図に表されるような状態の遷移をするsketchを作成してください。

画像

文章にすると次のような状況です。

  • 閲覧モードのウインドウサイズは100x100、背景は緑
  • dキーが押されたら作図モードに移行
  • 作図モードではウインドウの大きさを倍にし、それに応じて点の位置を相似の位置に移動、背景は白
  • マウスでクリックするとそのポイントに点を描画
  • 終了はqキーで、閲覧モード時のみ有効

まとめ

  • シーケンス図とステートチャート図の描き方とメリットを学びました。

学習の確認

それぞれの項目で、Aを選択できなければ、本文や演習にもう一度取り組みましょう。

  1. それぞれの図の目的とメリットが理解できましたか?
    1. 理解できた。気持ちよく納得した。
    2. 理解できた。しかし、今ひとつスッキリしない。
    3. 理解できない。
  2. それぞれの図を読み、描くことができるようになりましたか?
    1. できるようになった。
    2. 本文の図は読めるが、自分で描くことはできない。
    3. 読むことも描くこともできない。

参考文献

  • 『これだけでわかる!初歩のUMLモデリング―基礎から各種テクニックまで第一人者が伝授!! (@ITハイブックス)』⁠萩本順三 著、技術評論社
    • UML入門の良書。絶版であるのが残念。古書をあたってください。
  • 『オブジェクトモデリング表記法ガイド―例題で学ぶUML』⁠MISCOオブジェクト指向研究会 編著、今野睦 監修、プレンティスホール出版⁠
    • 私はUMLをこの書籍で学びました。大変分かりやすく記述されています。同じく絶版本。更に出版社は既に無いようです。これもよろしければ古書をあたってください。

演習解答

  1. 例えば次のようなシーケンス図が考えられます。

    画像
  2. コード例を示します。

おすすめ記事

記事・ニュース一覧