UTI UML教育研究所
トップページ> 読み物> コラム> 使えるUML 第10回
はじめるUML(全12回)
  はじめてみよう!
  モデル要素の整理整頓
  システム全体の構造(1)
  システム全体の構造(2)
  システム全体の構造(3)
  システム化対象の業務(1)
  システム化対象の業務(2)
  システムの動き(1)
  システムの動き(2)
  状態の移り変わり
  OCUPにチャレンジ!
  UML2.0総括(最終回)
続はじめるUML(全10回)
  使ってみよう!
  UMLによる業務分析
  営業職のOCUP受験体験記
  UMLによる要求分析
  インターメディエイト受験体験記
  UMLによるシステム分析
  アドバンスト受験体験記
  UMLによるシステム設計
  情報システム管理者が利用するUML
  続はじめるUML総括
使えるUML(全10回)
  使いこなしてみよう!
  物事を分けてとらえる
  コンポーネント図のいくつかの表現方法
  枠組みを使用してとらえる
  内容とその表現方法をわける
  パターンの表現
  続・パターンの表現
  モデルのモデル
  あいまいさを排除する
  「どのように(How)」から「何を(What)」へ
  大人のオブジェクト指向(最終回)
資格取得までのステップ
FAQ
教育コンテンツ
キャンペーン
ブックプラス
パートナープログラム
認定ユーザープログラム
メールマガジン登録
お問合わせ
使えるUML 第10回

パターンウィーバー(PatternWeaver) ver2.2
さらに使いやすく、新機能満載!
  • 多言語によるモデル開発をサポート
  • モデル駆動型のSOA(サービス指向アークテクチャ)をサポート
  • MS-Word形式へのドキュメント出力をサポート
  • RCP(Rich Client Platform)版の提供を開始
  • 洗練された各種ダイアグラム
  • 操作性の強化
  • リポジトリ(UML要素管理機能)の強化
  • ソースコード連携の強化

評価版がダウンロードできますので、ぜひお試しください。
http://pw.tech-arts.co.jp/download/community_edition.html

●商品に関するお問い合わせ
株式会社テクノロジックアート
e-mail : pw@tech-arts.co.jp
http://pw.tech-arts.co.jp/

2007.11.1 掲載
「どのように(How)」から「何を(What)」へ
前回に引き続き今回の記事でも、OCL(Object Constraint Language : オブジェクト制約言語)の続きを行っていきます。今回は、『「どのように(How)」から「何を(What)」へ』と題しまして、一般的なプログラム言語とOCLの比較を行いながら問い合わせ操作の定義を説明します。プログラミングの経験のある方は、OCLを学ぶことが新しいプログラミング言語を押し売りされることとは少し違うということがお分かりいただけると思います。プログラミングの経験がない方には難しい内容に感じられるかもしれませんが、今回はご容赦ください。

◇問い合わせ操作を定義する
オブジェクトを検索して返す操作を「問い合わせ操作」といいます。問い合わせ操作では、オブジェクトの状態やリンクの変更を行いません。OCLは、この問い合わせ操作を定義することができます。ここでは演劇の予約システムを例にしながらOCLの問い合わせ定義に親しんでいきましょう。
以下は、クラス図です。

図1 演劇の予約システム
図1 演劇の予約システム

ある公演の予約者が他にどのような公演を好んで見ているのかを分析するために、公演クラスには「予約者が予約している別の公演のリスト」の問い合わせ操作が記述されています。以下はこの操作を定義するOCLです。

図2 予約者が予約している別の公演のリスト(順序なし)
図2 予約者が予約している別の公演のリスト(順序なし)

  順序なし 順序あり
重複なし Set 重複するオブジェクトを含まない。関連はデフォルトでSetとなる。 OrderdSet 順序のつけれられたSet。
重複あり Bag 重複したオブジェクトを含むが、順序はない。SetかBagに対して、さらにドットをつなげた関連の誘導はBagとなる。 Sequence 重複を許し、順序を持つ。OrderdSetかSequenceに対してさらにドットをつなげた関連の誘導はSequenceとなる。
表1 コレクションの種類

それでは、OCL例のそれぞれの要素に注目しながら読み解いていきましょう。

  1. 定義する操作を表しています。また、返り値の型はSetです。表1にコレクションの種類を記述しましたので参考にしてください。
  2. 問い合わせ操作の定義を行うことを表しています。
  3. 演劇の予約の予約者(重複あり)を表しています。OCLでは「. <関連端ロール>」と記述することで関連するオブジェクトを誘導することができ、多重度が多の関連はデフォルトではSetとなります。予約の多重度は多なので「self.予約」は演劇に関連した予約オブジェクトのSetとなります。また、OCLではオブジェクト単体ではなく、オブジェクトのコレクションに対しても「. <関連端ロール>」を記述することができます。その場合、コレクションに含まれるオブジェクトのすべてに対して、関連端ロールを誘導した結果のコレクションを得ます。このときに結果の型は重複を許す型に変換されることに注意してください。「self.予約.予約者」は、Setのコレクションに対する誘導ですので顧客オブジェクトのBagとなり、重複した顧客が存在します。
  4. OCLはコレクションに対する多くの演算を標準で持っており、「-> <コレクション演算>()」と記述して使うことができます。「->asSet()」は重複のないSetにする演算で、(c)の重複した顧客のBagを重複のない顧客のSetにしています。ここまでで、公演のすべての公演予約者が手に入ります。
  5. その顧客の公演予約の公演です。「公演予約」までで予約のSetとなります。「公演予約.公演」だと公演のBagとなりますので、asSet()を行って公演の重複をなくします。
  6. (e)までで予約者が予約した公演のリストが手に入ります。しかし、この中には自分自身の公演も含まれています。自分自身の公演を削除するために、「->excluding(self)」を行います。

このようにして、予約者が予約している別の公演のリストが定義できました。しかし、返ってくる値はSetであるため、どの公演が予約者から好まれているのか順位づけすることができません。そこで、予約数の順番にソートしてみましょう。

図3 予約者が予約している別の公演のリスト(順序あり)
図3 予約者が予約している別の公演のリスト(順序あり)

  1. 順序のあるSetを返すために、この操作をOrderdSetとして宣言します。
  2. 「self.予約.予約者->asSet()」を「公演予約者」として定義しています。OCLではこのように変数を作成することができます。変数が使用できるのは「in」の中だけです。
  3. 前述のOCLにsortedBy()以下の記述が追加されています。sortedBy()では引数の値の大小によってソートが行われます。返り値の型は演算対象の型によってOrderdSetかSequenceとなります。
  4. sortedBy()はイテレータ演算と呼ばる演算の一種で、コレクションの要素を繰り返し取り出しながら評価を行います。イテレータ演算の引数ではコレクションの要素を使用することができます。ここでの「予約」はsortedBy()の対象の、公演の予約となります。
  5. 「->intersection()」はコレクションの積集合(両方に含まれるオブジェクト)を返します。当該の演劇の予約で、かつ公演予約者の公演予約を取得します。
  6. sum()もイテレータ演算の一種で、コレクションの要素を繰り返し取り出しながら合計を取得します。

このようにして、予約数の順番にソートされた公演のリストを取得することができます。

OCLを使用してこれで目的のリストを取得することができました。はじめてOCLに触れる方は難しさを感じたかもしれません。
しかしそれでもプログラミングの経験のある方は、一般的な命令型プログラミング言語(CやJavaなど)でどのようにコーディングすることになるか、ここで少し時間をとってイメージしてみてください − 入れ子のForループや合計を保存するための変数などがでてきそうですが、きっとすぐにはアルゴリズム全体をイメージすることはできないでしょう。こうしたプログラミング言語が「どのように(How)」を記述するのに対して、OCLのような宣言的言語では「何を(What)」を記述するので、ほとんどの場合にシンプルに表現できます。問い合わせ操作を定義する場合には、プログラミング言語よりもOCLのような宣言的言語のほうが適しています。

◇OCL(宣言的言語)からプログラミング言語(命令型言語)へ
システム開発でも操作をOCLで記述できれば理想ですが、実際にはプログラミング言語で実装することが多いと思います。しかしそれでもOCLで記述することが無駄にはなるとはいえません。ここでは、OCL式のガイドにしたがってプログラミング言語へ変換していくことを見ていきましょう。
ところで、先ほどプログラミング言語では「どのように(How)」を記述すると説明しましたが、プログラミング言語でもコードのすべてがHowになるわけではありません。Howは操作の内部実装にあたりますが、操作の宣言自体は「何を(What)」になります。OCL式をいくつかの部分に分けて操作(What)として切り出し、それぞれの操作を実装していくことで、OCLでの宣言的な構造を保ったままプログラム言語へおとすことができます。
プログラミング言語での操作の実装(How)は避けることができないものですが、それでもより多くのWhat、つまり操作に分割してより宣言的に実装することは良いプラクティスとなります。
先の例のOCL式から操作を切り出してみましょう。

図4 操作の切り出し
図4 操作の切り出し

上記の例のOCLから3つの操作を切り出しました。このようにして、OCLの式(What)から必要な操作(What)を、多少の修正は必要なものの比較的簡単に切り出すことができます。これらの切り出した操作を実装して、さらにそれらの操作を呼び出す実装を記述すればプログラム言語に落とすことができます。
また、このようにOCLにガイドされて得られたアルゴリズムはとても自然で美しいものになる傾向があります。

◇まとめ
今回は以下のことを学びました。

  • 問い合わせ操作を定義しながらOCLの読み方に親しんだ。
  • プログラミング言語が「どのように(How)」を記述するのに対して、OCLのような宣言的言語では「何を(What)」を記述する。問い合わせ操作にはOCLが適している。
  • プログラミング言語においても操作を分割して宣言的に実装したほうが良い。
  • OCLでプログラミングをガイドして、自然で美しいアルゴリズムを得ることができる。

今回はプログラミングの経験のない方には難しい内容だったと思います。また逆にプログラミングの経験のある方も宣言的言語の感覚は難しいものに感じられたかもしれません。違う言語で考えると違う答えが見つかるもので、言語が思考をガイドすることを肌で感じてもらえたなら嬉しく思います。ぜひOCLに親しんでプログラミングへも適用してみてください。


■筆者紹介
山下 智也/Tomonari Yamashita
株式会社テクノロジックアート テクニカルデプト UMLモデリングチーム