連載
【改訂版】初歩のUML
第6回
「関連」の理解をさらに深める
萩本順三 株式会社豆蔵
2003/5/2
第5回「クラスの依存関係と実現関係」までクラス図におけるさまざまな「関連」を説明してきました。では実際に、これらをどのように使ってモデリングするのでしょうか? 今回は、店舗の売り上げを例に、関連の理解をさらに深めていきましょう。
クラス間の関連の数は1つ? |
いままで使ってきた例では、2つのクラス間の関連の線は1つでしたね。しかし、2つのクラス間の関連が1つになるとは限りません。例えば、店舗の売り上げを集計するシステムのモデルを考えてみましょう。店舗はその日の売り上げを持つようにします。売り上げの細かな構造については、取りあえず保留にしておきましょう(図1)
しかし、その日の売り上げを持つということを満たしただけで、果たしてこのシステムの要求は満たせるのでしょうか? 例えば、月次売り上げはどうなるのでしょう。また、「月次ABC分析」(ABC分析:商品の管理手法の1つ。ABCの3ランクに分けてAランクを最重点商品として管理する)などを行うためには、月次、年次レベルで売り上げを持つ必要があります。では、売り上げを日次だけではなく月次、年次レベルも含めて保持するようにすればいいと考えますよね。ところが、店長から次のような要求が出たらどうしますか?(図2)
|
|
なるほど店長の言い分もごもっともです。さて、皆さんならこのモデルをどうしますか。私ならば、まずお客さん(店長)からこのような要求が出た時点で、モデルを取りあえず図3のように変更します(注1)。
図3には、2つのクラス間に2つの関連が引かれています。そして、それぞれの関連は、「売り上げを管理する」「履歴を管理する」という異なる意味が付与されています。このように、2つのクラス間には異なる意味を持ついくつかの関連を引くこともあります。
|
(注1)
このようにお客さんから要求を聞きながら大まかなシステムの概念構造をモデルとして整理していく作業を分析モデルといいます。しかし、実際のプログラムコードに落とすには、もっと詳細なクラス図を書く必要があります。このようなモデルを設計モデルといいます。分析モデルと設計モデルの詳細な説明についてもこの連載で取り上げる予定ですのでお楽しみに。
自己再帰的な関連 |
次は、図3のモデルを大規模な商店のモデルとして考えてみましょう。それぞれの売り上げは、「食品部」「衣服部」などといった部門によって管理されるとしましょう。その場合、図4のように店舗と売り上げの間に部門をいれたモデルで表現できます。
|
さて、ここからが少し複雑な問題となります。店長が次のようなことを言い始めました。
「この部門には、衣服部門の中に子供服、紳士服、婦人服といったサブ部門が必要なんだ。また、サブ部門を持たない部門もあるぞ。さらには、サブ部門のそのまたサブ部門が必要かもしれない」
うーむ。難しい注文ですね。部門とサブ部門があり、サブ部門がいくつ存在するか分からないとは、……どうしましょう。
これを端的にモデル化することはできないものでしょうか。そこで、まずはこの問題をオブジェクト図を使って表現してみましょう(図5)。
|
いかがでしょう? 図5のモデルからクラス図がイメージできますか? 「部門が部門を持つようにすればよいのでは?」という意見もありますね。そういう場合は、部門が部門を持つ構造を作成すればよいのです(図6)。
|
しかし図6は何か変だと思いませんか?
そうですね、1つのクラス図の中に、部門クラスが2つ存在するのはクラス図ではルール違反です。また、このモデルのままでは部門は1階層までで、それ以上の階層が存在することはできませんので、店長の考えを反映したとはいえません。
正解は、「部門が部門を構成する」ということを、部門クラスが同じ部門クラスを集約するように表せばよいのです。図7にクラス図を示します。これで、部門の階層化についても、ちゃんと表現できるようになりました。
|
対象問題をしっかりと分析する |
「売り上げ」については、売り上げクラスということで、かなり大ざっぱにモデル化していました。次は、この部分についてもう少しまじめに分析してみましょう。
物事を深く分析するためには売り上げというものがどのような構造になっているかを考察する必要があります。しかし、売り上げを考察するといっても漠然としてイメージがわかないでしょう。そこで、筆者がおすすめするのが、リアルな「もの」をイメージしながらモデリングする方法です。つまり、実世界にあるリアルな「もの」をまずイメージすることから始めるのです。リアルな「もの」とは、具体的に印刷されたものとか、表示されているものとか、実際に目で見える「もの」を想像することです。
この例では、お店に行って売り上げを端的に表しているリアルなものは何かを考えましょう。売り上げには取引という行為が伴います。この取引という単位で売り上げをとらえるというのはビジネスの鉄則です。そこで、店と客の間の取引を行った結果として残るレシートを、リアルな「もの」としてイメージしてみるのです(図8)。
|
レシートのイメージ(図8)をよく見ると、品目と個数と金額が繰り返し表示されている部分があります。まずはここに着目します。
◆繰り返されている部分をほかのクラスに分解する
もしこのように繰り返されている部分が存在する場合は、ほかのクラスに分解し、コンポジション(または集約関係)として表現します。
|
◆ライフサイクルが異なる部分をほかのクラスに分割する
次は、ライフサイクルに着目します。明細の属性をよく見てください。この中で「チョコを2つ買った」という結果は、取引が行われたときに発生しています。しかしチョコとその単価という属性はどうでしょうか。これは取引が発生したときに発生したと考えるべきでしょうか?
いいえ、そうではないですね。チョコと単価は、取引をする前からすでに存在していたものです。そこで、これらの属性をまとめて別のクラスとして分割します。これら属性をまとめるクラスとしては何が適切でしょうか?
それは商品です。ということで、商品クラスを作成し、明細クラスから分割します。商品クラスには、商品名と単価を属性として持ちましょう。ついでに商品を管理するための商品コードも付けてみましょう(図10)。
|
このようにして作成された商品は、明細の構成物と考えてコンポジションとしました。しかし本当にこれでよいのでしょうか? 例えば、ほかの人がコーラを買った場合、商品との関係はどうなるでしょうか? ちょっとそのときのイメージを示してみましょう(図11)。この図のように、2枚のレシートに現れる商品のオブジェクトは、管理上1個のオブジェクトで表すのが適切です。なぜなら別々に2つある必要がないからです。従って、明細と商品の関連は「N対1」となります。また、明細オブジェクトは、商品オブジェクトを参照しているにすぎないということになり、コンポジションではなく関連が適切だということになります。
|
このような理由により、クラス図は、図12のようになります。
|
操作を割り付けてみよう |
さて、ここでしっかりと分析された売り上げを店舗と部門に関係付けて、部門ごとの売上合計、サブ部門ごとの売上合計という操作を割り付けてみましょう。
|
この図では、2つの新たな記法を使用しています。それぞれの記法について下記に説明しましょう。
派生属性:明細クラスの属性「小計」を見てください。この小計には“/”(スラッシュ)が付いています。このようにスラッシュが付けられた属性のことを派生属性といいます。派生属性は、自分の関係しているオブジェクトの情報から加工・算出できる値を保有する概念的な属性です。操作によってオブジェクトが一時的に保有するのか、それとも属性として本当に持つかどうか、まだ明らかにしたくない場合に使用します。派生属性は、分析段階にて使用され、操作の結果だけにすべきか、実際の属性を持つべきかどうかを設計に委(ゆだ)ねる際に使用するものです。
関連の方向性(誘導可能性):関連はデフォルトでは双方向性を持ちます。これは、関連から生成される2つのオブジェクトは両方相手を知っており、お互いにメッセージを交換し合うことを意味します。しかし、明らかに片方のオブジェクトからしかメッセージを送る必要がない場合に双方向性を持つとするならば、実装局面においてはプログラムコードに冗長性をもたらすことになります。また、モデルの意味上においても分かりづらさをもたらしてしまいます。このようなときには、関連の端に矢印を書くことで、関連の方向性を明確にします。図13では、明細から商品に向けて矢印を書くことで、明細は商品を知っているが、商品は明細を知らないという意味をモデルに付加しています。こうすることで、商品クラスが明細クラスから独立していることを強調することができます。このように関連の方向性をつけることを誘導可能性と呼びます。
今回は、店舗の売り上げを例に、関係の理解をさらに深めてきましたが、いかがでしたか。関連の理解は深まりましたでしょうか? 今回取り上げたように、問題領域を分析する際には、まずリアルな「もの」を想像するためのコツとして現実世界に存在する印刷物をイメージするというのは非常に有効な手段です。たとえ実際にそのような印刷物がなかったとしても、その印刷物を自作してみることをおすすめします。そして、自作した印刷物の内容を分析してみるのです。その際に、下記の方法を使って印刷物の構成要素を分解していきます。そうすることで、問題領域を深く理解するためのモデルが作成できるようになります。
- 繰り返されている部分をほかのクラスに分解し、コンポジションとする
- ライフサイクルが異なる部分をほかのクラスに分割し、関連で結ぶ
(コラム)リアルモデリングのすすめ |
今回紹介したように、印刷物などリアルなものをイメージして、それを基に、モデリングを進めるというのは私が業務分析を行う際によく使うテクニックです。なぜ、このような方法を考え出したかというと、オブジェクト指向によるモデリングの特徴に起因します。 オブジェクト指向によるモデリングは、どうしても思考の世界に入り込むため、良くも悪くも「あいまいさ」を残してしまうことがあるのです。リアルモデリングは、実際の印刷物を作成することでこの「あいまいさ」を排除できます。また、問題領域を分析する際の目的(関心事)を明確にすることができます。 今回の例の場合は、「取引の内容」と「取引の単位」こそが、問題領域(ビジネス)の最も重要視すべき関心事なのです。このビジネスの関心事を理解するためにも、そこでやりとりされる重要な情報を印刷物として作成してみたらどうなるかということを考えると、ビジネスの関心事がはっきりと見えてくるものです。 このような印刷物を作成してみて、その印刷物がどのようにやりとりされ、ライフサイクル(いつ発生し、いつまで保持されるべきか)はどうなのか、などと考えることで、ビジネスにとって、最も重要な事項をモデリングの対象とできるようになります。皆さんもぜひ、一度リアルモデリングにチャレンジしてみてください。 |
今回はこれでおしまいです。
次回は、オブジェクトの動的側面を観察するためのモデリングについて取り上げていきます。
IT Architect 連載記事一覧 |