アジャイルモデリング(AM)
公式サイト
モデリング成果物>UML 2 クラス図

UML 2 クラス図の概要

by Scott W. Ambler, Copyright 2003

UMLのクラス図(Object Management Group 2003)は、オブジェクト指向分析・設計の大黒柱です。UML2クラス図では、システムのクラスと、その相互関係(継承、集約、関連を含む)、クラスの操作と属性を表します。クラス図は、概念/ドメインモデリングや詳細設計モデリングなど、さまざまな目的に使います。私自身はクラス図をホワイトボードに書くのが好きなのですが(簡単な道具の方がいろいろな使い方ができるので)、このページのほとんどの図は、正確な表記法が分かりやすいように、作図用のソフトウェアを使って書いてあります。

この成果物説明では以下の内容について議論します。

 

1. 概念クラス図

図1に示すのは、大学システムにおける簡単な概念モデルのUMLクラス図の最初の部分です。クラスは3つの区画に分かれた四角形で表されていて、一番上にはクラス名が、真中にはクラスの属性一覧が、一番下にはメソッドの一覧が書かれています。クラスに属性とメソッドの箱を書いている時点で、私はおそらくこのモデルで設計上の判断をしてしまっています。概念モデリングをするのが目的なら、これはやってはならないことです。別の方法は、クラスの区画を2つにして、片方に名前を、もう片方に責務を書くことです。これはCRCモデルに近いやり方です(ですから、このようなアプローチを取りたい場合には、私はUMLクラス図でばなくCRCカードを使います)。また、クラスの名前だけを書いた箱を使って、クラスとクラス間の関係だけに集中することもできます。ただし、それが目的なら、私はおそらくORM図の方を作成することでしょう。ひとことで言うと、AMの「適切な成果物を使おう」のプラクティスに従って、各モデリング技法にもっとも合った使い方をしたいと思っています。

 

図1 概念クラス図の下絵

 

「登録」は関連クラスです。これはリンククラスとも呼ばれるもので、メソッドや属性を持つ関連をモデリングするために使います。関連クラスは通常、分析時にモデリングされ、その後リファクタリングされて、設計時には図2のようになります(図2はまだ概念モデルの段階ですが、いくらか設計っぽくなっています)。現在のところ、少なくとも私の知る範囲では、主流のプログラミング言語の中で、責務を持った関連の概念をサポートしているものはありません。このようにすれば直接ソフトウェアを構築できるため、私はたいてい、関連クラスは使わずに、分析作業中に解決してしまいます。これはあまり純粋なモデリング方法ではありませんが、プロジェクトの利害関係者を含めたチームの他のメンバーが関連クラスの表記法や概念について学ばなくてもよいという点で実用的です。

図2図1を書き直したもので、関連クラスが解決されています。「ゼミ」クラスに「順番待ち名簿」という属性を追加してもよかったのですが、ここでは関連としてモデリングすることにしました。実際に表されているのは関連だからです。つまり、ゼミオブジェクトはゼロ以上の学生オブジェクトの順番待ち名簿を保守しているのです。UML2.0では、属性も関連もプロパティであり、基本的に同じようなものとして扱われています。また、ここでは関連が属性と操作の組合せとして実装されることも示しています。私はモデルをシンプルにしておいて、関連を実装するための属性と操作が存在するはずだと考える方が好みです。さらに、いずれにしてもこれは詳細設計の問題なので、概念モデルに示すのは適切ではありません。

 

図2 初期の概念クラス図

「順番待ち名簿に載っている」の関連は単方向になっていますが、これは両方向に呼び出し合う必要がないためです。AMの「中身はシンプルに作ろう」のプラクティスに従って、モデルを作り込みすぎないようにします。今現在双方向の関連は必要ではないので、モデリングしないでください。「学生」クラスと「登録」クラスの間の「〜に登録する」の関連も、同じ理由で単方向になっています。この関連の場合、学生オブジェクトは、現在取っているゼミだけでなくこれまでに取っていたゼミの記録も残していて、自分がどの登録レコードと関係があるかを知っています。この関連をたどることで、学生オブジェクトの平均点を計算したり、これまでに取っているゼミの情報を返すことかできます。また、「登録」と「ゼミ」の間にも「〜に登録する」の関連があって、取っているゼミの一覧を学生オブジェクトが作成できるようになっています。「教授」クラスと「ゼミ」クラスの間の「指導する」の関係は双方向になっていますが、これは、教授オブジェクトは自分の教えているゼミを知っていて、ゼミオブジェクトは誰が自分を教えているかを知っているためです。

私は概念モデリングを行うとき、属性とメソッドにそれぞれ「Attribute Name」および「Method Name」という書式(単語の間に空白を入れるという意味です)で名前を付けることにしています。一貫した意味のある命名規則を使うことで図が読みやすくなります。これはAMの「モデリング標準を適用しよう」のプラクティスを使ったときの重要な利点です。また、図2では、属性やメソッドの可視性をほとんどモデリングしていないことに注意してください。可視性は設計時に重要な問題となりますが、今のところは無視してかまいません。また、クラスのメソッドのシグニチャも完全に定義しているわけではありません。私はこの作業もたいてい設計時まで手をつけずにおきます。

この情報にもとづいて、1つの例外を除いたすべての関連について、確信を持って多重度を判断することができました。判断できなかった1つについては、ノートを付け、利害関係者とさらに議論をできるようにしてあります。ノートの中の疑問符の使い方に注意してください。私はいつも図上の不明な情報にはこのように印をつけて、調査が必要なことを忘れないようにしています。

図2ではUMLの制約をモデリングしています。この場合は「ゼミ」と「学生」の間の関連に付いている「{ordered FIFO}」です。基本的に学生は、先入れ先出し方式(FIFO)で順番待ち名簿に載せられます。言い換えると、先着順で名簿に載るということです。UMLの制約を使うことで、複雑な情報や重要な情報を、UMLのダイアグラムに正確にモデリングすることができます。UMLの制約は「{制約の記述}」という書式でモデリングします。この制約の記述はどんな書式でもよく、述語計算を使うこともできます。私自身は、形式的な制約を使うよりも、UMLのノートを使って普通のことばで書く方が、読みやすくて気に入っています。

 

2. 設計クラス図

近日公開

 

図3 設計クラス図

 

3. クラス図の作成方法

概念クラス図を作成し、発展させるには、次のものを反復的にモデリングする必要があります。

設計クラス図を作成し、発展させるには、次のものを反復的にモデリングする必要があります。

 

3.1 クラス

オブジェクトとは、システムに現れるあらゆる人、場所、もの、概念、イベント、画面、レポートなどのことです。オブジェクトは、ものごとを知っていますし(属性があります)、ものごとを行います(メソッドがあります)。クラスとはオブジェクトを代表するもので、多くの点で、オブジェクトを作成するテンプレートにすぎません。クラスはオブジェクト指向アプリケーションの主要な構成要素となります。大学には何千人もの学生が通学していますが、モデリングするのは「学生」という1つのクラスだけで、そのクラスが学生全体を表します。

 

3.2 責務

一般的にクラスは、3つの区画に分かれた長方形を使ってモデリングします。一番上の区画にはクラス名を、真中の区画にはクラスの属性を、一番下の区画にはクラスのメソッドを記述します。モデルに含まれる初期のクラスは、CRCモデリングを行う場合と同じように見つけ出すことができますし、初期の責務(属性とメソッド)も同じです。属性とはオブジェクトに関して格納されている情報(少なくともオブジェクトに関して一時的に保持されている情報)であり、メソッドとはオブジェクトやクラスが行う事柄です。たとえば、学生は、学生番号、名前、住所、電話番号を持っています。これらはいずれも学生の属性の例です。また、学生はコースに登録し、コースから脱退し、成績証明書を要求します。これらはいずれも、学生が行う事柄の例であり、メソッドとして実装(コーディング)されます。メソッドは、オブジェクト指向版の関数や手続きだと考えるとよいでしょう。

ここで適切な詳細レベルについて考えてみましょう。図2でモデリングした「学生」クラスには、「住所」という属性があります。しかし、よく考えてみると住所は複雑です。たとえば通りや市の情報を持っている他、振る舞いも持っている可能性があります。おそらくこれは図4に示すようにモデリングした方がいいでしょう。「住所」クラスには、住所を構成する各データ用の属性がモデリングされています。また、2つのメソッドが追加されています。1つは住所が有効かどうかを確認するためのもの、もう1つはラベルとして出力するためのもの(おそらく封筒用に)です。「住所」クラスを導入することで、「学生」クラスはより凝集性が高くなりました。住所に関するロジック(有効性確認など)を持たなくてよくなったからです。そして「住所」クラスは「教授」クラスなど他の場所で再利用できるようになり、全体としての開発コストを下げることができます。さらに、学生に複数の住所を持たせるというニーズが発生した場合(学生は学期中に自分のいつもの送付先住所とは違った場所、たとえば寮などに住んでいるかもしれません)、その情報をシステムで追跡する必要があるかもしれません。別のクラスとして住所を実装しておけば、この振る舞いを追加する場合にも簡単に実装できます。

 

図4 学生と住所(概念クラス図)

「学生」クラスの機能で興味深いのは「登録資格がある」という責務です。下線が引いてあるのは、インスタンスレベル(たとえば「取っているゼミを返す」など)ではなく、クラスレベルの責務であることを表しています。ある責務がクラスレベルのものかを判断する基準は、そのクラスの個々のオブジェクトに適用されるのではなくクラスに属するというのが道理にかなっているかどうかです。この例では、「ゼミに登録する」のシステムユースケースで呼び出されるBR129「登録資格を判断する」をこの操作で実装します。

図2の「ゼミ」クラスを見直し (refactoring) て、図5に示すクラスを作成します。このような見直しはクラスの正規化と呼ばれるもので(Ambler 2004)、クラスの振る舞いを見直して、凝集性を高め、クラス間の結合度を下げます。ゼミとは実際に行われるコースの講義です。たとえば「CSC148 コンピュータ科学入門」というコースは、5つのゼミとして講義が行われるかもしれません。「名前」および「授業料」という属性は「コース」クラスに移され、さらに「コース番号」が追加されます。getFullName()メソッドでは、コース番号「CSC148」とコース名「コンピュータ科学入門」が連結されてコースの完全な名称として返されます。これはgetメソッドと呼ばれるもので、オブジェクトに関連したデータ値を返す操作です。getメソッドとそれに対応するsetメソッドはクラスの開発には必要ですが、通常は当然あるものと想定し、見苦しくならないようモデルには記述しないでおきます(特に概念クラス図の段階では)。

 

図5 正規化されたゼミクラス(概念クラス図)

図6図5のコースクラスにget/setメソッドを追加するとどうなるかを表したものです。get/setメソッドは概念モデルに記述するには適さない詳細であり、私の経験では詳細設計の図にさえも記述するべきではありません。私なら、コーディング指針に「全プロパティにはget/setメソッドを作成すること」と書き、それだけにしておきます。モデルにget/setメソッドを書く人もいますが、私は書いても効果がないばかりか、図がややこしくなって分かりにくくなるだけだと思っています。

 

図6 アクセスメソッドを追加したコースクラス(設計クラス図に少し近づいている)

== Course: コース Name: 名前 Course Number: コース番号 Fees: 授業料 ==

 

3.3 関連

多くの場合、オブジェクトは別のオブジェクトと関連(あるいは関係)を持っています。たとえば、図2にもいくつかの関連があります。学生はゼミの「順番待ち名簿に載っている」、教授はゼミを「教える」、ゼミではコース「の講義が行われる」、教授は住所「に住んでいる」などといった具合です。関連は、その関係に参加しているインスタンス(オブジェクト)のクラス2つを結ぶ線としてモデリングします。

UMLクラス図で関連をモデリングするときには、図6のように、2つのクラスを結ぶ細い線で表します。関連はかなり複雑になる場合があるので、図上では関連線の上にいくつかの事柄を記述することができます。ラベル(オブションですが付けることを強く推奨します)は、通常、関連を説明する1つまたは2つの単語です。たとえば、教授はゼミを「教える」のようになります。

 

図6 関連の表記法★図6は2つめですね

 

ただ単に教授がゼミを教えると知るだけでは十分ではありません。教授はいくつのゼミを教えるのでしょうか。ゼロでしょうか、1つでしょうか、それとも複数でしょうか。さらに、関連は往復両方向の場合もよくあります。教授がゼミを教えるだけでなく、ゼミは教授によって教えられるのです。そう考えると次のような疑問が出てきます。あるゼミを何人の教授が教えることができるのでしょうか。誰も教えないゼミというのはあり得るのでしょうか。ここで言いたいのは、関連の多重度も明らかにする必要があるということです。関連の多重度は、各方向に1つずつ、線の端に指定します(指定可能な多重度の書き方を表1にまとめます)。

 

表1 多重度の指定

指定方法

意味

0..1

0または1

1

必ず1

0..*

0以上

1..*

1以上

n

必ずn(ただしn > 1)

0..n

0以上n以下(ただしn > 1)

1..n

1以上n以下(ただしn > 1)

 

関連にはその他に、ラベルをどの方向に読むべきかを指定することができます。これは、方向指定子 (direction indicator) と呼ばれる黒い三角で表します。図5で、「ゼミ」クラスと「コース」クラスの間の「〜の講義が行われる」関連に付けられているのがそれです。このシンボルがついていることで、この関係が「ゼミではコースの講義が行われる」のだと読むことができます。「コースではゼミの講義が行われる」のではありません。方向指定子は、ラベルをどの方向に読めばいいかが明確でない場合に指定するべきです。ただし私は、ラベルが明確でない場合には、ラベルを付け直すことを考慮すべきだと考えています。

線の端にある矢じりは、関連をどちら向きにたどれるかを表します。線の片側に矢じりがついていれば単方向、矢じりがない、あるいは両側に付いている場合は双方向です。正式には、双方向の関連には両端に矢じりを付けるべきなのですが、つけないやり方が一般的です(これまでの図を見ると分かるように、私は付けない方が好みです)。

関連のそれぞれの端には、関連におけるオブジェクトのコンテキストを表すロールを指定することもできます。私は、その情報に価値がある場合にのみロールをモデリングすることにしています。たとえば「〜に登録する」という関連における「学生」クラスのロールが「登録された学生」であると分かっても、モデルには何の役にも立ちません。私はAMの「モデルはシンプルに書こう」のプラクティスに従って、関連のラベルから何のロールなのかがはっきりと分からない場合にだけ、ロールを記述することにしています。たとえば、再帰的関連の場合や、2つのクラス間に複数の関連がある場合などです。

 

3.4 継承(汎化)関係

異なるクラス間に類似性の認められることがよくあります。2つ以上のクラスで同じ属性やメソッドを持っていることはしょっちゅうです。同じコードを繰り返し記述するのは好ましくないので、このような類似性を利用するメカニズムが欲しくなります。継承がそのメカニズムです。継承とは「〜である」や「〜と同様である」という関係をモデリングするもので、これによって既存のデータやコードを簡単に再利用することができます。AがBを継承しているとき、AはBのサブクラスであり、BはAのスーパークラスであるといいます。さらに、AがBのすべての属性およびメソッドを継承している場合には「純粋な継承」であるといいます。UMLのモデリング表記法では、サブクラスからスーパークラスの向きに閉じた矢じりのついた線を引いて、継承を表します。

図2では、「学生」クラスと「教授」クラスの間に多くの類似点があります。同じような属性を持っているだけではなく、同じようなメソッドも持っています。これらの類似点を利用して、新しい「人」というクラスを作成し、「学生」クラスと「教授」クラスにそのクラスを継承させました。図7を見てください。この構造は「人」がルートクラスになっているため、「人」の継承階層と呼ばれます。「人」は抽象クラスなので、このクラスから直接オブジェクトを作成することはできず、学生と教授の類似点を表しているだけです。抽象クラスであることは、クラス名をイタリックで表記して表します。これに対して具象クラス(オブジェクトをインスタンス化することのできるクラス)の名前は普通のテキストで記述します。「学生」と「教授」のどちらのクラスも、名前、電子メールアドレス、電話番号を持っているため、これらの属性は「人」クラスに移します。また「駐車券を購入する」のメソッドも2つのクラスに共通しているため(このメソッドは図2を書いた後で見つかったものです)、これも親クラスに移します。この継承関係をモデルに追加したことで、行わなければならない作業量が減りました。これらの責務を2度実装するのではなく、「人」クラスで一度だけ実装して、それを「学生」および「教授」で再利用することができます。

 

図7 継承階層

 

3.5 コンポジション関連

ときには1つのオブジェクトが別のオブジェクトから構成されることがあります。たとえば飛行機は、機体、翼、エンジン、着陸装置、フラップなどから構成されます。図8はコンポジションの使用例を示したもので、ビルが1つ以上の部屋から構成され、さらに部屋は複数の小さな部屋から構成される可能性がある(コンポジションは再帰的に使うことができます)ということをモデリングしています。UML2では、弱い形のコンポジションである集約の概念をサポートしなくなりました(これはUML1.xで白抜きのひし形で表されていたものです)。

 

図8 コンポジションのモデリング

 

私は「〜の一部である」のルールを固く信じています。何かが何かの一部であるという言い方が意味をなしていたら、コンポジションが妥当である可能性は高くなります。たとえば、「部屋はビルの一部である」とは言えますが、「住所は人の一部である」という言い方は意味をなしません。別の指針として、部分側のライフサイクルが全体側に管理されている場合、コンポジションが妥当だと考えることができます。たとえば、飛行機がエンジンのアクティビティを管理しているといった具合です。関連の代わりにコンポジションを使うべきかどうかを判断するときには、Craig Larman (2002)の次のことばが役に立つでしょう。「迷ったときにはそのままにしておきなさい」。残念なことですが、モデリング担当者の多くはいつコンポジションを使うかに苦戦しています。実際のところ、コーディングレベルでは、関連とコンポジションにはほとんど違いがないのですが。

 

3.6 語彙

Agile Database Techniques(Ambler 2004)で、私はXMLデータ構造をモデリングするときの語彙の重要さについて議論しています。語彙では、エンティティ型とその責務、エンティティ型間の分類学的な関係、エンティティ型間の存在論的な関係のセマンティクスについて定義します。セマンティクスとは意味ということばを格好よく言い換えただけです。何かのセマンティクスを定義しているときには、その意味を定義しているのです。分類学とは、エンティティ型を階層に分類することです。図9に人を使ってその例を示します。存在論は分類学よりさらに深いものです。分類学が分類階層を扱うのに対し、存在論は、ある主題に関する知識だけでなく、その主題に含まれるエンティティに関する一連の関係やプロパティの知識まで、表し、伝えます。

 

図9 大学にいる人の分類学

 

概念モデルのセマンティクスは用語集として表現するとよいでしょう。図9には興味深い側面がいくつかあります。

  • これまでの図で使ってきた3つの区画ではなく、クラスを「1つの区画」で捉えています。これは、エンティティ型の責務ではなく、エンティティ型間の関係について調査しているためです。

  • UML2.0の汎化セット (generalization set) の概念を使っています。これは基本的に、継承の矢印の横にそのセットの名前のラベルを付けただけです。このラベルはUML1.xで弁別子と呼ばれていたものです。「人」には3つの汎化セットがあります。「国籍」、「役割」、「性別」の3つです。

  • これらの汎化セットは重なり合います。人はこれらのロールのそれぞれに分類することができます(たとえば外国人の男子学生など)。これを多重分類と呼びます。

  • 下位の汎化セットを表すことができます。「役割」汎化セットの「学生」がその例です。

  • この例にはありませんが、汎化セットの中には他の汎化セットと相互排他的なものがあります。その場合、エンティティ型は1つのセットにしか入ることができません。これを単一分類と呼び、2つ(以上)の弁別子の間にXOR(排他的論理和)の制約を付けてモデリングします。

 

 

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


推奨文献

 

その他の文献

アジャイルモデリング(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.