Skip to content.

Sections
Personal tools
You are here: Home » 技術文書 » UML » Java プログラマーのための UML

Document Actions
Java プログラマーのための UML

(株)永和システムマネジメント     平鍋健児
作成日:1998,11/28
   UMLとは

あなたが Java プログラマだとして,大きなソフトウェアの設計をしたり,それを他人に説明したり,あるいは今解こうとしている問題を明確に定義しようとする時,どうしているだろうか.

一人で小さなプログラムを作るという作業においては,あまりこのような問題は起こらないかもしれない.しかし,プログラム開発を職業にしている場合,あるい はある程度の規模のソフトウェアをチーム開発する場合は,必ず他人とのコミュニケーションが必要になる.それは顧客との仕様打ち合せであったり,内部でのプログラム構造の設計ミーティングであったりするだろう.

一人で開発を行う場合でも,システム全体を見ながら考えをまとめ, 機能的で保守性が高いすっきりとした構造に仕上げるには,何らかのビジュアルな図が役に立つことが多い.

UML(Unified Modeling Language)とは,オブジェクト指向分析, 設計においてシステムをモデル化する際の記法(図法)を規定した言語(ビジュアル・ランゲージ)である. これを理解し活用することで,あなたのプログラマとしてのコミュニケーション能力は 大幅にアップすることは間違いない.


  UML の歴史

ソフトウェアの図法としては,古くはフローチャートやデータフロー図, データベースのER 図などが知られている.オブジェクト指向が脚光を浴び, 90年代前半にオブジェクト指向分析,設計を支援する様々な方法論(メソドロジー)が出現した. Grady Booch による Booch Method,Jim Rumbaughによる OMT(Object ModelingTechnique)などが有名である.

問題は,各方法論で図の記法が異なっていたため,その後しばらく記法に纏わる「宗教論争」がおこり, 記法の統一がなされなかったことである.表現されている概念が同じであるのに表記法が異なっていたため, 実際に記法を使用しようとする設計者たちは混乱してしまった. 例えば,OMT ではクラスは長方形で描かれたのに対して, Booch Methodではクラスは雲型で書かれていたのである (この雲型を書くためのテンプレート定規が存在した!).

記法統一への試みは,1994年に始まる.Grady Booch と Jim Rumbaugh が手を組み, Unified Method 統合への協力が開始された. また,ユースケースの概念を初めて著したOOSE (Object Oriented Software Engineering)の Ivar Jacobson も1995年にこれに加わり,UML 1.0 が 1997 年に発表された. この間,多くの他の研究者からの提案が加えられている. UML 1.0 は OMG(Object Management Group) に提案され, 改良された UML 1.1 が,OMG より標準化認定を受けることになる.

UML1.1 は現在,オブジェクト指向設計の標準記法として広く知れ渡るに到っている. また,現在この3人(3大メソドロジストと呼ばれる)は,共にRational Software 社に籍を置いている.


3大メソドロジスト
方法論者 方法論
Grady Booch Booch Method
Jim Rumbaugh OMT(Object Modeling Technique)
Ivar Jacobson OOSE(Object Oriented Software Engineering)

UML統一の歴史
時期 出来事
1994年 Grady Booch と Jim Rumbaugh が Unified Method の統合開始
1995年 Ivar Jacobson が協力
1996年 UML 0.9, 0.91 リリース
1997年1月 UML 1.0 発表
1997年11月 UML 1.1 OMG標準として採択


  UML はビジュアル・ランゲージである

UML は,オブジェクト指向分析,設計においてモデリングを行う言語である. 扱おうとしている問題を明らかにしたり(分析),その解決法を組み立てる(設計)際, 問題を図としてモデリングする過程を助ける.

UML は言語であるということを協調したい. UML は,描かれたモデルを複数人で共有してコミュニケーションしたり, 自分一人でも考えをまとめ,アイディアを展開する作業を助けるビジュアル・ランゲージなのである.

UML は,で規定されている図をではダイアグラムと呼ぶ.ダイアグラムには以下の物がある.


UML図
ダイアグラム 役割 対象フェーズ
ユースケース図 システムの機能要件を定義 分析
クラス図 システム内のクラス間の相互関係を表現 分析,設計
シーケンス図 オブジェクト間のメッセージ交換の時系列表現 分析,設計
コラボレーション図 オブジェクトの集団の協調動作の表現 分析,設計
アクティビティ図 システムの動作の流れの表現 分析
状態図 クラスのオブジェクトの取りうる状態を表現 分析,設計
コンポーネント図 システムを構成する実行可能モジュールやソースコードの物理的構造を表現 設計
配置図 システムを構成する物理的なマシンや装置の継りを表現 設計


また,各図内の要素を階層的にグルーピングするために,パッケージ図が定義されている.

  分析,設計プロセスと UML

UML では記法(ノーテーション)とその意味(セマンティクス)が定義されているが, その記法をどの開発フェーズでどのように使用するか,という開発プロセスは意図的に定義されていない. 大まかな使用法の例は以下のようになる.

分析フェーズにおいてユースケース図を中心に要求を分析,定義する. ユースケースからシナリオ(具体的なシステム使用法の脚本)を書き, そこから問題領域のクラスやオブジェクトを抽出する. それらをクラス図を使ってモデリングしたものを要求モデルとする. アクティビティ図,状態図,シーケンス図,コラボレーション図なども補助的に使用される. この要求モデルではシステムを顧客やユーザの言葉でモデリングする ことが重要である.ここでは UML は,顧客やユーザとのコミュニケーションを助ける言語となる.

要求モデルを元に,決定されたアーキテクチャ(後述)の中に論理的な設計モデルを構築する. やはりクラス図を中心に,アクティビティ図,状態図,シーケンス図,コラボレーション図が使用される. 扱う問題領域によって,不可欠な図もあるだろうしほとんど使用されない図もあるだろう. 設計モデルの構築の際には,「デザインパターン」という設計イディオムを利用する方法が注目を浴びている. 設計者はパターンのボキャブラリを持っていた方がよい.このようにして作成された設計モデルが, 設計フェーズの成果物となる. ここでは UML は設計者間のコミュニケーションのための言語となる.

一方,システムの論理的な側面とは別に「アーキテクチャ」を決めておくことが重要となる. アーキテクチャは使用するハードウェアや分散環境,データベース,通信,GUI, 言語やライブラリなどの物理的および環境的要因からなる開発基盤で決定されることが多い. これらのソフトウェア,ハードウェアの構成はそれぞれコンポーネント図や配置図で記述することができる.

分析と設計は順序よくウォーターフロー型で行われると思われるかもしれないが, 実際には小さな単位でこの作業を繰り返しながらインクリメンタルにモデルを洗練していく手法が 現代的である.ただし,最初にも書いた通り UML ではプロセスを規定していない.


   Java プログラマーのための UML(1)

Java プログラマーの中には,まだ UML を使ったことのない読者も多いと思う. 簡単に UML のイメージをつかんでもらうために, 実際のJava のクラスのコードを UML で表現してみよう. 本来 UML は分析,設計というコーディングより前の行程で使用するものであるが, ここでは Java プログラマーのために,先にコードを示してそれを UML で説明する, というリバースエンジニアリングを試みる.

  例題アプレット

では,題材となるプログラムを先に見てもらおう. このアプレットは,複数の色名の中から幾つかを選んでそれを通知するものだ. このようなアプレットのコードは,Java プログラマにはおなじみだろう.


MyApplet プログラム
import java.awt.util.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import myProject.database.MyDatabase;

public class MyApplet extends Applet implements ActionListener {
    Checkbox[] colors;
    MyDatabase db;
    Button ok;
    int count;

    public MyApplet() {
        colors = new Checkbox[] { new Checkbox("red"), new Checkbox("blue") };
        db = MyDatabase.open("DatabaseServer:/home/myDatabaseFile.db");
        ok = new Button("OK");
        add(colors[0]);
        add(colors[1]);
        add(ok);
        ok.addActionListener(this);
        count = 0;
    }

    private void increment() {
        count++;
    }

    public void actionPerformed(ActionEvent e) {
        for (int i = 0; i < colors.length; i++)
            if (colors[i].getState())
                db.add(colors[i].getLabel());
        increment();
    }
}


このコードの実行例の画面である.

My Applet 実行画面
myApplet実行

このプログラムは自作のアプレット - MyApplet を作っている. MyApplet には複数のチェックボックスと1つのOK ボタンがある. OK ボタンが押されると, チェックボックスの内容を自作のデータベース - MyDatabase に格納すると同時に, 内部のカウンタを1つインクリメントしている. 例えば,MyDatabase はリモートホストにあるデータベースとネットワークで結ばれていることを想定する.

では,このプログラムを種々の UML ダイアグラムに表現してみよう.

  クラス図

UML でもっとも中心的な役割を果たすのは,クラス図である. クラス図は,クラス同士の継承,関連などの構造的な関係を表している. また,クラスが持っているデータ属性やメソッドも書くことができる.

クラスは長方形で表現し,3つのパーティションを持つことができる. 一番上のパーティションにはクラス名を書き,2番目に属性(変数)を, 3番目に操作(メソッド)を書く.また,インターフェイスは小さい円を書き, それを実装(implements)するクラスと結ぶ.(クラスと同じ記法を用いる場合もある)

クラスの表現
クラスの表現

クラス間の関係は,線を用いてクラスの長方形同士を結ぶ. 関係を示す線には,以下のような記号を使う.

関係の表現
関係の表現

関連(association)は,もっとも単純な結び付きを示す. 修飾されることによってより具体的な意味になる.修飾については後述する.

汎化(generalization)は,矢印の先のクラスが元のクラスの汎化された意味を 持っていることを示す.あるいは元のクラスは先のクラスを特殊化(継承)すると 言っても良い.java ではextendsに対応する.

依存(dependency)は,矢印の元のクラスが先のクラスに依存することを示す. 先のクラスが変更された時,右のクラスに影響を及ぼすことを示す.java での依存の形態は様々であり,メソッドの引数や戻り値となる場合, メソッド中で new される場合,インターフェイスを利用する場合などがある.

洗練(refinement)では,矢印の元のクラスが先のクラスを洗練したものとなっている ことを示す.java では,インターフェイスの実装(implements)などが 対応する.

4つの関係の中でも関連は非常に幅の広い概念であるため,関連の両端に修飾を 行うことでその意味をさらに具体化することができる.以下の様な修飾の種類がある.

関連の修飾
関連の修飾

集約(aggregation)は,図中で左のクラスが右のクラスを保持していることを示す. 菱形が塗りつぶされる時,さらに強い集約の形態であるコンポジション(composition) と言われ,完全に右のクラスが左の一部であることを示す.java では, 左のクラスが右のクラスをインスタンス変数として含み,左のクラスが消滅すれば 右のクラスも消滅するような場合に用いられる.

誘導可能性(navigability)は,図中で左のクラスから右のクラスが辿れる(navigable) ことを示す.java では,左のクラスが右のクラスをインスタンス変数として 含んでいる場合などが典型である.

多重度(multiplicity)を追加することで,関連の両端に対応するオブジェクト の個数を書くことができる.数字1つで明確な個数を書いても, n..m と言った範囲指定でもよい.* という複数個(0個を含む)指定もよく使用される.

では,この例題アプレットをクラス図にしてみよう.

クラス図
myAppletクラス図

この図から何が読み取れるだろうか.

  1. MyApplet は Applet を継承している.
  2. MyApplet は ActionListener インタフェースを実装している.
  3. MyApplet は Button を ok という名前で内蔵している.
  4. MyApplet は Checkbox を複数,colors という 名前で順序管理された列{ordered}として内蔵している.
  5. MyApplet は MyDatabase と関連し,MyApplet から MyDatabase を辿れる.
  6. Button は ActionListner インターフェイスに依存し, ActionListner を通して MyApplet オブジェクトと通信する.
  7. MyApplet は count というデータ属性とincrement(), actionPerformed() というメソッドを持つ.
  8. MyDatabase クラスは add() というメソッドを持つ.

MyApplet クラスがどのようなクラスとどのような関係で結び付いているかが目で見て分かる. クラス図は,コードから静的な構造を抽出して,視覚的に表現したものと言えよう.



シーケンス図

今度は,このコードをシーケンス図に書いてみよう. シーケンス図は,オブジェクト同士がどのように相互作用しているかを示す. シーケンス(順序)という名前から分かる通り,この図の焦点はメッセージ呼び出しの順序である.actionPerformed() が呼ばれた時の動きを追って見る.

シーケンス図
ボタン押下時のシーケンス図

シーケンス図では,主体はクラスではなくてオブジェクトであることに注意する. 長方形の中の名前は「オブジェクト名:クラス名」となる. (UML ではオブジェクトは下線を引いて表す)

MyApplet のオブジェクトが,イベントソースであるButton オブジェクトから actionPerformed()メッセージを受けてからの動作を時間順に表現している.

  1. ok:ButtonオブジェクトがmyApplet:MyAppletオブジェクトに actionPerformed() メッセージを送る.
  2. myApplet:MyAppletオブジェクトはcolor:CheckBoxオブジェクトに getState() メッセージを送り,結果(state)を受け取る.
  3. state が true であれば,さらに getLabel() メッセージを送る.
  4. db:MyDatabaseオブジェクトに add() メッセージを送る.
  5. 最後にmyApplet:MyAppletオブジェクトが自分自身の increment() メソッドを起動する.

シーケンス図は,コードから動的なメッセージ伝達を抽出して時間順に 視覚的に表現したものと言えよう.

コラボレーション図

次にコラボレーション図を見てみよう.コラボレーション図では,協 調動作するオブジェクト間の関係(リンク)と,そこで伝達されるメッセージを表現す る.オブジェクト同士の関連のことを,UML ではリンクという.シーケンス図 が時間的な順序をもっとも重視しているのに対して,コラボレーション図では 複数のオブジェクト間のリンクとコラボレーション(協調関係)にスポットが あたっている.

ボタン押下時のコラボレーション図
コラボレーション図

この図では, ok:Button, myApplet:MyApplet, color:CheckBox, db:MyDatabase という4つのオブジェクトが メッセージを伝達しながら協調している様子が描かれている.メッセージには 番号が付いており,この順に伝達が発生する.1 の actionPerformed() メッセージの中で 1.1 の getState(), 1.2 の getLabel(), 1.3 の add(), そして 1.4 の increment() メッセージが起動される.枝番でメッセージの スタック上のネストが表現されている.

シーケンス図では時間順に並んでいたメッセージ伝達が,コラボレーション図では オブジェクト間リンクの空間的な配置の中に並びかえられている.

コラボレーション図は,コードから動的なメッセージ伝達を抽出し,それ をオブジェクト間の協調関係の中で視覚的に表現したものと言えよう.


   Java プログラマーのための UML(2)

Java のコードに対応するように クラス図,シーケンス図,コラボレーション図を示したが,さらに他の図についても例を挙げて行きたい.

  ユースケース図

このアプレットのユースケース図を書いて見る. 本来はユースケースを最初に定義して開発を進めることになる. ユーザや顧客との要求分析のコミュニケーションに役立つ図だ.

ユースケース図
ユースケース図


人の形のアイコンは「アクター」と呼ばれ,システムの外部の操作者 を定義する.また,横長の楕円でシステムの機能である「ユースケース」を 定義する.このシステムは,非常に単純な機能しか持たないため,当然 ユースケースも単純なものとなる.

ユースケース図は,システムが外部の操作者とどのように関っているかを捉えている.

状態図

このシステムでは,あまり重要な状態が見当たらないが,ここでは チェックボックスの状態を書いて見た.もう少し仕様が明らかであれば, データベースの状態なども状態図の候補になるであろう.

チェックボックスの状態図
状態図

黒い丸で開始地点を示す.最初チェックボックスは「選択されていない」状態である. 「クリック」というイベントによって,「選択されている」状態と「選択されていない」状態を順に移行する.

状態図は,システムの中の主要なクラスのオブジェクトがどのような状態遷移を行うかを明確にする.

  コンポーネント図

コンポーネント図では,ソフトウェアの構成を表現する. コンポーネントの候補は,ソースコードファイルやコンパイル済コード, 実行形式のコードなどが対象になる.それぞれのコンポーネント間に依存関係の矢印が引かれている. コンポーネント同士の依存は,依存元に変更があれば依存先に影響が出る,ということを示している.

コンポーネント図
コンポーネント図

ここでは,例として MyDatabase のコードが native の dll に依存しているとした. また,コードを示した MyApplet.java は java の AWT パッケージに依存する.

配置図

配置図では,ハードウェアの構成を表現する. 実際の装置や計算機ノードの配置関係と,それらの継りを示している.

配置図
配置図

ここでは,例として DatabaseServer というマシンがアプレットが動作するマシンとは別に存在し, それらが TCP/IP のネットワークで SQL NET プロトコルを使って接続されているとした.


まとめ

Java プログラマーの読者を対象に,簡単な例で UML の説明を試みた. 繰り返すが,UML はビジュアル・ランゲージである. これを理解すればSmalltalk, Eiffel や C++ といった Java 以外のプログラミング言語の利用者ともコミュニケーションを取れるようになるし, プログラム言語に依存しない設計能力もつく. これからオブジェクト指向分析,設計を行う上で, UML はデザインパターンと共に必須の知識となるであろう.


質問,感想は,平鍋まで.
Copyright (C) Kenji Hiranabe 1998, 1999




この記事への評価にご協力をお願いします。

良かった 普通 イマイチ