連載
» 2005年02月02日 12時00分 公開

The Rational Edge:UML 2.0のキホン:コンポーネント図の詳細解説

Rational Edgeより:本稿ではコンポーネント図と、新しいUML 2.0仕様のストラクチャ図について解説する。

[Donald Bell(IBM Global Services,IBM),@IT]
ALT 本記事は、IBM developerWorksからアットマーク・アイティが許諾を得て翻訳、転載したものです。

 本稿はUnified Modeling Language(UML)で絶対不可欠なダイヤグラムに関する連載の続編である。UMLのクラス図に関する前回の記事「UML’s class diagram」(The Rational Edge、2004年9月)では、クラス図の表記がUML 2.0の全ストラクチャ図の基本になっていることを説明した。今回は引き続きストラクチャ図に触れながら、コンポーネント図の詳細を解説する。

◆ ダイヤグラムの目的

  コンポーネント図の最大の目的は、システムコンポーネント間の構造上の関係を描くことだ。UML 1.1では、1つのコンポーネントがファイルや実行イメージなどのインプリメンテーション項目を示していた。残念ながら、これはCOMコンポーネントなどを示す「コンポーネント」という用語の一般的な用法とは矛盾する。UMLのリリースが進むにつれ、UMLにおけるコンポーネントの意味は変化していった。UML 2.0では、コンポーネントという概念の本来的な意味が(UML 1.1に比べて)完全に変わってしまっている。UML 2.0では、1つ以上のインターフェイスを持つシステムやサブシステム内の自立したカプセル単位のものをコンポーネントとしている。UML 2.0仕様には厳格な規定はないものの、一般的に「代替可能な」モジュールでインプリメントされるものを示す設計上のより大きな単位がコンポーネントだとされる。しかし現在では、UML 1.xと異なり、コンポーネントはあくまでも論理的な設計段階の構成体になった。つまり、コンポーネントが動作をカプセル化し、指定されたインターフェイスをインプリメントするため、設計上のコンポーネントのインプリメンテーションを再利用したり、別のもので代用することが容易になったのである[注1]。


[注1] UML 1.xでコンポーネントと呼ばれていた物理的なものは、UML 2.0では「成果物」と呼ばれる。成果物はファイル、実行イメージ、スクリプト、データベースなど、物理的な単位になっている。物理ノード上にあるのは成果物だけで、クラスやコンポーネントには「居場所」がない。しかし、成果物がコンポーネントなどの各種classifier(つまりクラス)を明示する場合もある。1つのコンポーネントは同じもしくは異なるノード上の複数の成果物で明示することもできるため、1つのコンポーネントを間接的に複数のノードにインプリメントすることもできる。

 コンポーネントベース開発(CBD)では、ソリューションのモデリングを開始するに当たって、コンポーネント図が設計者に自然なフォーマットを提供してくれる。コンポーネント図を使えば、システムに必要な機能がコンポーネントによってインプリメントされているかどうかを設計者が検証できるようになり、完成システムが確実に条件を満たすようにできる。

 さらに、コンポーネント図は各グループにとっても便利なコミュニケーションツールとなる。図は、重要なプロジェクトの出資者やインプリメンテーション担当者に見せることができる。コンポーネント図は、一般的にシステムのインプリメンテーションスタッフ向けに考えられたものだが、図があれば構築されるシステムの全体像を早く理解できるようになるため、普通はコンポーネント図の提示が出資者の安心につながる。

 コンポーネント図は、これから構築していくシステムをアーキテクチャの観点からハイレベルで描くため、デベロッパにとっては便利なものだ。これにより、デベロッパはインプリメンテーションのロードマップを明確な形にしていくことができ、作業の割り当てや必要なスキルの向上に関する判断も下せるようになる。システム上で動作する論理ソフトウェアコンポーネントを早い段階で把握できるため、コンポーネント図はシステム管理者にとっても便利だ。システム管理者は、マシンや実行イメージの実体をダイヤグラムから特定することはできない。しかし、コンポーネントやコンポーネント間の関係を早い段階で知ることができる(これにより、システム管理者が事前計画を立てられるようになる)。つまり、コンポーネント図がシステム管理者にとって歓迎すべきダイヤグラムであることは明らかだろう。

◆ ノーテーション

 コンポーネント図はUML図の中で最も描きやすいものの1つである。図1は、以前のUML 1.4の表記を使った簡単なコンポーネント図を示しており、この例では、Inventory Systemのコンポーネントを利用するOrder Systemのコンポーネントという2つのコンポーネント間の関係を示している。図から分かるように、UML 1.4のコンポーネントは、大きな長方形の左側から2つの小さな長方形が突き出した形で描かれる。

ALT 図1 この簡単なコンポーネント図は、Order Systemの一般的な依存をUML 1.4表記で示している

 上記のUML 1.4表記はUML 2.0でもサポートしている。しかし、UML 1.4の表記法では大規模なシステムに十分対応することができなかった。このような理由から、UML 2.0では本稿で後述するようにコンポーネント図の表記法を大幅に強化している。UML 2.0の(表記法の)方でスケーリング機能を拡張し、(盛り込める)情報量も増やした。

 では、UML 2.0に沿ったコンポーネント図の基本を1つ1つ見ていこう。

◆ コンポーネント図の表記の基本

 UML 2.0でコンポーネントを描く作業は クラス図によるクラスの描画にかなり近づいた。実際、UML 2.0ではコンポーネントはクラスの概念が特殊なバージョンになったものにすぎない。つまり、クラスのclassifierに適用される表記ルールは、コンポーネントclassifierにも適用される(読者諸兄がストラクチャ図について書いた筆者の前回の記事をクラス図を中心にだいたい読んで理解していれば、コンポーネント図は順調に理解できると思う)。

 UML 2.0ではコンポーネントが長方形で表記され、オプションで縦の区画が付く。UML 2.0のハイレベルで抽象化されたコンポーネントは、コンポーネントの名前とコンポーネントのステレオタイプテキストやアイコンの入った長方形だけでモデリングできる。コンポーネントのステレオタイプテキストは「<>」で、コンポーネントのステレオタイプアイコンは2つの小さい長方形が左側に突き出した長方形となっている(コンポーネントを示すUML 1.4表記の要素)。図2は、UML 2.0仕様で可能な3つの異なるコンポーネントの描き方を示している。

ALT 図2 コンポーネント名の区画描画方法(クリックすると拡大

 図上でコンポーネントを描くときは、コンポーネントステレオタイプテキスト(「コンポーネント」を二重のアングルブラケットで囲んだもの。図2参照)やアイコンを必ず含めることが重要だ。なぜならば、UMLでは、ステレオタイプclassifierのない長方形がクラスエレメントだと解釈されてしまうからだ。コンポーネントのステレオタイプやアイコンはこの長方形をコンポーネントエレメントとして識別する。

● コンポーネントのインターフェイス(実装済み/必須)のモデリング

 図2のOrderコンポーネントは、どれも有効な表記エレメントを示している。しかし、典型的なコンポーネント図にはもっと多くの情報が含まれている。コンポーネントエレメントは、名前区画の下をもう1つ別の区画で区切ることができる。前述したように、コンポーネントは自立した単位で、1つ以上の公開インターフェイスを実装している。これらの実装済みインターフェイスは、コンポーネントがその消費者/クライアントに提供する正式なサービス契約を示している。図3は、Orderコンポーネントが提供する必須インターフェイスを示した2番目の区画を持つOrderコンポーネントを示している[注2]。


[注2] コンポーネントは自立した単位だが、ほかのコンポーネントが実装済みのサービスに依存する場合がある。このため、コンポーネントの必須インターフェイスを文書化しておくと便利だ。


ALT 図3 Orderコンポーネントの必須/実装済みインターフェイスを示す別区画

 図3で例示したOrderコンポーネントでは、コンポーネントがOrderEntryとAccountPayableのインターフェイスを実装する。さらに、このコンポーネントではPersonインターフェイスを実装する別のコンポーネントも必須になる[注3]。


[注3] 図3では、あらゆる状況を含めた形でOrderコンポーネントを示していない。現実のモデルでは、OrderEntry、AccountPayable、およびPersonの各インターフェイスがこのシステムのモデルの中で示される。


● インターフェイスをモデリングする際のもう1つのアプローチ

 UML 2.0では、コンポーネントの実装済み/必須インターフェイスを示す方法がもう1つ導入されている。この方法では、長方形を基本とし、その中にコンポーネントの名前が示される。そして、UML 2.0仕様で「インターフェイスシンボル」と呼ばれるものが長方形の外側に接している。図4はこの2番目のアプローチを示している。

ALT 図4 コンポーネントの実装済み/必須インターフェイスをインターフェイスシンボルを使って示す(図3とは)別のアプローチ

 2番目のアプローチでは、先端に丸の付いたインターフェイスシンボルがコンポーネントの実装済みインターフェイスを示している。この「ロリポップ(棒付きキャンディー)」シンボルは、インターフェイスclassifierの実現関係を手っ取り早く示すための手法だ。一方、先端に半円の付いたインターフェイスシンボル(「ソケット」)は、コンポーネントの必須インターフェイスを示す(いずれの場合も、インターフェイスの名前はインターフェイスシンボル自体のそばに記されている)。図4図3は大きく異なるように見えるが、どちらの図も、OrderコンポーネントがOrderEntryとAccountPayableの2つのインターフェイスを実装し、OrderコンポーネントがPersonインターフェイスを必須とするという同じ情報を提供している。

● コンポーネント間の関係のモデリング

 あるコンポーネントと別のコンポーネントとの関係を示すときは、ロリポップとソケットの表記に(クラス図と同様に)依存矢印を含める必要がある。ロリポップやソケットの付いたコンポーネント図では、依存矢印が利用側の(必須)ソケットから出て、その矢じりが図5のように提供する側のロリポップに接続される。

ALT 図5 Order Systemのコンポーネントとほかのコンポーネントの依存関係を示すコンポーネント図

 図5は、Order SystemコンポーネントがCustomer RepositoryとInventory Systemの両方のコンポーネントに依存している様子を示している。図5では、「CustomerLookup」と「ProductAccessor」というインターフェイス名が重複している点に注意したい。例では、これが不必要に繰り返されているように見えるが、実際の表記では、インプリメンテーションの違い(1つのコンポーネントが小さい必須インターフェイスのサブクラスとなる1つのインターフェイスを実装するなど)に応じてコンポーネントごとに異なるインターフェイス(そして異なる名前)を使うことができる。

● サブシステム

 UML 2.0では、サブシステムclassifierはコンポーネントclassifierの特殊なバージョンになる。このようなことから、サブシステム表記エレメントはコンポーネント表記エレメントから同じルールをすべて継承する。唯一の違いは図6のように、サブシステム表記エレメントには「コンポーネント」の代わりに「サブシステム」というキーワードが付くことだけだ。

ALT 図6 サブシステムエレメントの例

 UML 2.0仕様は、サブシステムとコンポーネントの違いに関してかなり漠然としている。この仕様では、コンポーネントやサブシステムをモデリングの観点から全く同様に扱う。UML 1.xと比較すると、このUML 2.0モデリングの多義性は新しい。しかし、それには理由がある。UML 1.xでは、サブシステムはパッケージと見なされ、このパッケージ表記がUMLを扱う現場の多くの人間を混乱させた。このような理由から、UML 2.0ではUML 1.xユーザーの大半が理解しているように、サブシステムと特殊なコンポーネントを同列に扱っている。この変更は状況を不明瞭にしてしまったが、それはUML 2.0仕様が間違っているというより、むしろ現実を反映したものだといえる。

 読者諸兄はおそらく、サブシステムエレメントではなくコンポーネントエレメントを使うのがいつか分からず頭をかきむしっていることだろう。率直にいって、筆者にも正しい答えは見当たらない。ただいえるのは、UML 2.0仕様では、サブシステムではなくコンポーネントを使う状況の判断はモデル作成者の方法論による、ということになっている。UMLを方法論に絶対に依存しないようにし、ソフトウェア開発のあらゆる場面で利便性を発揮させることに役立つため、筆者個人としてはこの回答が気に入っている。

◆ コンポーネンと図を理解するための次のステップ

 コンポーネント図は図の中でも理解しやすい部類に入るので、基本以外に学ぶべきことはない。しかし、1カ所だけやや高度な部分がある。

● コンポーネントの内部構造の提示

 いずれは、コンポーネントの内部構造を表示することが理にかなう場面が出てくる。筆者は、クラス図に関して言及した「UML's class diagram」で、クラスの内部構造をモデリングする方法を示した。今回筆者は、ほかのコンポーネントによって構成されたコンポーネントの内部構造をモデリングする方法に重点を置く。

 コンポーネントの内部構造を示すには、そのコンポーネントを通常より大きく描き、包含するコンポーネント名区画の中に内部の部品を置くだけでよい。図7はStoreのコンポーネントの内部構造を示している。

ALT 図7 このコンポーネントの内部構造はほかの複数のコンポーネントによって構成されている(クリックすると拡大

 図7で示されている例では、StoreコンポーネントはOrderEntryインターフェイスを実装し、Accountインターフェイスを必須とする。Storeコンポーネントは、Order、Customer、Productの3つのコンポーネントで構成されている。StoreのOrderEntryおよびAccountの両インターフェイスシンボルにはコンポーネントの端に四角が付いていることに注意したい。この四角はポートと呼ばれる。極めて簡単に説明すると、コンポーネントの実装済み/必須インターフェイスと内部パーツの関連性をモデリングするための手法を提供するのがポートだ[注4]。ポートを使うことで、この図はStoreコンポーネントの内部パーツを外部から切り離すことができる。

 図7では、OrderEntryポートがOrderコンポーネントのOrderEntryインターフェイスに処理を委譲する。また、内部のCustomerコンポーネントが必須とするAccountインターフェイスは、Storeコンポーネントが必須とするAccountインターフェイスポートに委譲されている。Accountポートに接続することで、Storeコンポーネントの内部パーツ(Customerコンポーネントなど)は、ポートのインターフェイスに実装された未知の外部要素の代理をローカルに立てることができる。必須となるAccountインターフェイスは、Storeコンポーネントの外部コンポーネントによって実装される[注5]。


[注4] 実際のところ、ポートはどのようなタイプのclassifier(クラスや、そのほか自分のモデルが持つ何らかのclassifier)にも当てはまる。本稿では内容を簡略化するため、コンポーネントclassifierをポートとする。

[注5] 通常、ポートとインターフェイス間の依存関係を描くときは、依存する(必須)インターフェイスがすべての処理ロジックを実行時に処理することになる。しかし、このルールにも例外は許される。依存するインターフェイスへ単に処理を委譲するだけでなく、包含するコンポーネント(ここの例ではStoreコンポーネントなど)に独自の処理ロジックを持たせることも全く問題ない。

 図7では、内部コンポーネント間の相互接続が図5のそれと異なることに気付くだろう。これは、コラボレーションが図のインスタンスや役割を示すため、内部構造の描写が実際にはclassifier(ここではコンポーネント)の中でネスティングされたコラボレーション図になっているためだ。内部コンポーネント間でモデリングされた関係は、UMLで「アセンブリコネクタ」と呼ばれているものによって示されている。アセンブリコネクタは、1つのコンポーネントの実装済みインターフェイスと、別のコンポーネントの必須インターフェイスを結び付ける。アセンブリコネクタはロリポップとソケットのシンボルを並べて描かれる。アセンブリコネクタをこのように描くと、ロリポップとソケットのシンボルがかなり読みやすくなる。


 コンポーネント図は、設計者がプロジェクトの初期段階で描くことの多い極めて重要な図だ。だが、コンポーネント図はシステムのライフサイクル全体を通じて役に立つ。コンポーネント図は、システムのアーキテクチャをモデリングして文書化するため、実に貴重な存在だ。コンポーネント図はシステムのアーキテクチャを文書化するため、デベロッパと、これからこのシステムの管理者になろうとする者には、システムの理解を助けるに当たってこの作業が重要になるだろう。

 コンポーネント図は、ソフトウェアシステムの導入図に対する入力としても機能するが、このことについては筆者の次回の連載で触れる。


本記事は「The Rational Edge」に掲載された「UML basics: The component diagram」をアットマーク・アイティが翻訳したものです。


「The Rational Edge」バックナンバー

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ

マーケット解説

- PR -