*begin*back*foward*end*contents

開発手法編 -
第20章 DRO
(Discovery of Requirement Objects)

要求の中からオブジェクトの候補を見つけ、それをクラスとして具体化する思考過程は、何段階かのフェーズに分類して表すことができる。それぞれのフェーズは、分析者の思考の中で無手順に繰り返され、オブジェクトが明確な型(クラス)を持つようになる。そのようなクラスをいくつか関係付けることで要求モデルは完成される。

このようなオブジェクトモデリングにおける分析者の思考過程を手順的な手法として示したものがDROである。DROには、多分に恣意的で不完全な面が含まれている。思考を手順化するということ自体、現実の思考と隔たりがあり、作為的なものである。(これは、Drop全般にも言えることであるが..)しかしながら、このような限界を知った上でDROを理解すれば、要求をモデル化する際、有効に活用することができるだろう。

DROは、「第15章 シネマスコープモデル」によって見つけられたオブジェクトの候補をベースとする。オブジェクトの候補に対し、オブジェクト間のインタフェースとオブジェクトの内部構造に着目しながら、システム要求において重要となるオブジェクトを見つけだしクラス構造を定めていくのである。

20.1 DROとは

利用目的

DROを利用する目的は、要求のモデル化にある。要求をモデル化するということは、抽象化された理想的なソフトウェア環境上に、要求を実現するためのクラスの構造を具体化することである。ここでの理想的なソフトウェア環境とは、ソフトウェアが実際に実装されるフレームワークやコンポーネントといった具体的なソフトウェア環境を想定しないものを意味する。

このように、抽象化されたソフトウェア環境に要求モデルを作り上げる効果は何だろうか? それは、実装環境の細かなルールに気をとられることなく、要求に基本的なデータ構造とインタフェース構造に注目しながらオブジェクトモデリングすることで、ユーザ要求に的を絞った抽象モデルの世界に開発者の意識を引き込んでいけることにある。それによって開発者は、ソフトウェアを実装するフェーズにおいても、要求モデルをアーキテクチャモデルの揺るがない基盤とすることができるのである。

使われるフェーズ

システム開発においては、問題領域分析フェーズ、また、コンポーネント開発においては、コンポーネント要求をモデル化するという目的でコンポーネント分析フェーズで使用される。

ドキュメント化

DROは、静的構造モデル動的構造モデルを使ってモデリングを進める方法を提供するものである。よって新たに表記法を提供するというものではない。DROによって作成されるドキュメントは、要求モデル(何枚かのクラス図)とオブジェクトレイアウトカードである。

オブジェクトレイアウトカードとは、DROによってクラス化されたオブジェクトの簡易ドキュメントのことをいう。クラス図は、システムの部分または全体をクラス構成で表すことが目的となるが、オブジェクトレイアウトカードは、要求を実現するための代表的なクラスのおおまかな仕様を表すことが目的とされる。以下のようなクラスがオブジェクトレイアウトカードの作成対象となる。

  • コンポーネント(またはフレームワーク)を利用するにあたり、コンポーネントユーザが意識すべきクラス
  • 複数人のチームでソフトウェアを開発する際に、開発者間のインタフェースとなるクラス

図20-1にオブジェクトレイアウトカードのレイアウトを示す。オブジェクトレイアウトカードには、「インタフェースカード」と「ストラクチャカード」という2種類の様式があり、それぞれ、ProcessとDataManageに属するオブジェクトに対応する。は図のようにカード型にしてもよいが、複数のオブジェクトを並べた表形式にしてもよい。また、記述される内容は、実装に近いもの(たとえば型や引数定義)を含めても、そうでなくても(たとえば日本語)よい。これらは対象問題に併せて分析者が決めればよい。

sorry this is image
図20-1 オブジェクトレイアウトカード

考え方・使い方

DRO手法では、できるだけスピーディにシンプルな要求モデルを完成させるように心がけることが重要である。時間をかければよいモデルができあがるという考えはあまりよい結果をもたらさないだろう。時間をかけすぎてしまうことで、モデルが詳細になりすぎて理解し辛くなったり、要求の基本部分から逸脱してしまうことが多いからである。問題領域の規模にもよるが、シネマスコープモデルと併せて半日から1日程度でモデルを仕上げるように心がけるとよいだろう。

DRO手法をルールとして考えてしまうと、結構手順が多く時間がかかりそうに思える。しかし、DROをルールと思ってはならない。あくまで分析を手助けする手法として使うものである。そう考えると、ルールから解放され、DROを思考のモデルとして自由に使いこなすことができるようになり、スピーディに要求モデルを作り上げることができるだろう。

DROは、Dropの中の手法という位置付けとなっているが、Dropから切り離して利用することも可能である。

20.2 DRO手法詳説

DROは図20-1に示すように、4つの作業フェーズで構成される。

次より、それぞれのフェーズの作業項目について解説しよう。

sorry this is image
図20-2 DRO手法の作業フロー

sorry this is image

1.1 クラスの役割と責任の明確化

シネマスコープモデルによって抽出されたオブジェクトの候補を、システム要求の実現という観点から眺め、クラスとしての役割と責任を明確に定義する。

システムを開発する上で、役割が曖昧なオブジェクトはこの段階で完全に排除する。このようなオブジェクトは、要求を説明するためにシナリオに現れていた名詞がそのままオブジェクト化されたものかもしれない。 たとえば、会計システムにおける「記帳者」や「端末」などというオブジェクトは、シナリオの中に現れたとしても、それは会計システムの実装には直接的に関係しないオブジェクトと考えるのが自然である。よって、このようなオブジェクトの候補はクラス化してはならない。

しかしながら、「端末」というオブジェクトを、会計伝票が複数のクライアントから仕訳入力を受け取るためのオブジェクトの名前としているのなら、名前付けに問題がある点は別として、システムにとって必要とされるオブジェクトということになる。その際の役割は「クライアントからの仕訳データを受け取り、サーバ側に送ること」ということになり、その責任は、「端末から入力される仕訳データのトランザクションの管理」ということになるだろう。

クラスの役割については、オブジェクトの持つ本来の役割だけではなく、「第18章 再利用基盤モデル 」の役割レイアVPD(View、Process、DataManage)に基づいた分類を行う。 会計システムにおける「端末」オブジェクトは制御のクラス化であるため、Processに属することになる。また、仕訳データは、仕訳データを管理する「仕訳オブジェクト」ということになるので、DataManageに属する。「会計伝票」は、仕訳オブジェクトの見せ方(View)と考えることができる。

  • View ..画面や印刷物などをクラス化したもの
  • Process ..要求を実現する制御をクラス化したもの
  • DataManage ..永続的なデータ管理が必要とされるクラス

1.2 Viewの排除、PD分割

上記役割レイアのうち、DROで対象とするのはProcessとDataManageだけである。Viewは意識的にこの段階で分析対象から排除される。なぜなら、Viewのモデル化はあまりにも実装環境のコンポーネントやフレームワークに依存したものであるため、モデル化による効果があまりない。よって、Dropでは、Viewは、アーキテクチャモデル(実装環境のコンポーネントやフレームワークに依存した設計モデルである)において具体化されるものと定める。

分析対象から排除されたViewは、開発者から完全に忘れ去られるものではない。ここで定義されたViewのモデルはアーキテクチャモデルに引き継がれることになる。また、Viewは「見せ方」を受け持つクラスであるため、「何を見せているのか?」という考察からDataManageに属するクラスを数多く発見することができる。たとえば、会計伝票オブジェクトは、仕訳オブジェクトや勘定科目オブジェクト、担当者オブジェクトなどの存在によって初めて会計伝票オブジェクトという見せ方(View)が実現されることになるであろう。つまり、Viewから入出力するための制御やデータ要素に注目してオブジェクト化することで、ProcessやDataManageに属するオブジェクトを見つけることができるのである。

Viewに属するオブジェクトは、分析対象から除外されるため厳密なクラス構造を確定できないことになるが、クラス図中にクラスとして現すことは問題としない。たとえば、会計伝票クラスとしてクラス図に表してもよい。なぜなら、Viewに属するクラスを示すことでProcessやDataManageに属するクラスの使われ方がより明らかになるからである。

ProcessとDataManageに分類されたクラスは、以下のように異なった観点によって詳細化し、それぞれオブジェクトレイアウトカードを作成することになる。

Process
システム実行時の動的側面を考察しながら、クラスのインタフェースを明確にしていく。
DataMange
クラスの内部の属性を明らかにしながら、クラスとクラス関連の最適な構造を作り出す。
( 開発システムの形態とPD分割 )

開発対象のソフトウェアシステムの形態によって、ProcessかDataManageのどちらかに偏ってオブジェクトが発見されるのが一般的である。たとえば、小規模なビジネスアプリケーションなどでは、Processは殆ど見あたらずDataManageが多く見つかるだろう。また、ツール開発やミドルウェア開発などでは、Prcoessが多く見つかり、DataManageは少ないかもしれない。これは、開発システムの形態が、制御中心なのかデータ中心なのかということに違いがある。制御中心であればProcess、データ中心であればDataManage、というように分析に集中すべきレイアをどちらかに定めることは分析のテクニックとしてよい方法である。両者をバランスよく抽出するよう心がけたり、均等な分析時間をかけたりするのは誤ったやり方である。

sorry this is image

DataManageに位置付けられるオブジェクトは、永続性のあるデータの管理を目的とするオブジェクトである。具体的には、OODBの永続オブジェクトであったり、RDBのテーブルにマッピングされるオブジェクトであったり、自らシリアライズする機能を持つオブジェクトであったりする。

2.1 要素分解

要素分解では、DataManageに属するオブジェクト候補を構成要素に分解することで、発見しにくい無形のオブジェクトや、問題における基礎となるデータ構造を見つけだしてクラス化する。

1.集約による分類

全体と構成要素の分類

オブジェクトの構成要素に着目して、要素オブジェクトを全体オブジェクトから分類する。この場合、全体オブジェクトの役割は、単に部分を束ねるだけになることもある。

例:
sorry this is image
図20-3 全体-部分

繰り返し項目の分離(1対N項関連の抽出)

オブジェクトから繰り返されるデータ項目を見つけだし、繰り返される項目をオブジェクトとして分離する。繰り返し項目として取り出されたオブジェクトも構成要素オブジェクトの一種である。

例:
sorry this is image
図20-4 繰り返し部分のクラス化

2.オブジェクトのライフサイクルによる分類

オブジェクトのライフサイクルとは、オブジェクトの生成・消滅のタイミングや、変更されるタイミングなどを観察して、オブジェクトの属性を性質別にグループ化し、最終的に別オブジェクトとすることである。たとえば、マスタとトランザクションというデータ分類はこれに属する。マスタオブジェクトとは、トランザクションオブジェクトからキーによって指し示されるオブジェクトであり、トランザクションオブジェクトよりも永続オブジェクトとして長い間システムに存在することになる。このようなオブジェクトの関係はマスタとトランザクションにクラスを分割しておななければならない。

例:
sorry this is image
図20-5 ライフサイクルによる分類

3.役割による分類

オブジェクトの役割とは、オブジェクトの属性ではなく操作に着目し、独立可能な操作グループを新たなクラスとして必要な属性と共に分類することである。分類されたクラスはProcessクラスとして「2.Processのモデル化」にてクラス化が進められる。このような分割の必要性は、DataManageはできるだけデータを管理するための簡潔な操作しかおかないようにすることで、汎用的なデータ操作コンポーネントという位置付けを維持することにある。これによって、DataManageに属するクラスの複数アプリケーションでの共有利用性を高めることができ、統合化されたシステムの中枢となるデータ管理をオブジェクトで実現できるのである。

また、抽出されたProcessオブジェクトは、再利用コンポーネントとしての可能性が生まれる。

例:
sorry this is image
図20-6 役割による分類

2.2 クラスの統合化

統合化は、オブジェクト分解工程までで抽出された複数オブジェクトの共通点に着目することにより、クラスの構造を再整理する。

オブジェクト分解工程完了後に、抽出された複数のオブジェクトの類似性に着目しながら、次の条件を満たすオブジェクトは、1つのオブジェクトに統合化する。

  • 意味的に同じオブシェクトで属性に若干の違いがある。
  • 意味的に同じオブシェクトで操作に若干の違いがある。
  • 継承を使用するくらいにオブジェクトの操作の特徴の差を見いだせない。

例:
sorry this is image
図20-7 クラス統合

2.3 属性と関連の詳細化

個々のクラスの内部構造に着目し、操作の具体化とクラス間の関連の具体化をおこなう。

1.オブジェクトID(キー)の付与

それぞれのオブジェクトに対し、インスタンスをユニークに識別するためのキーとなる属性を決定する。このようなキーは複数のインスタンスの中から指定したインスタンスを見つけだす必要がある場合に作成しなければならない。キーには、オブジェクトをユニークにするものなら何でも使える。たとえば請求書クラスが請求者名でユニークになるのであればOKである。しかしながら、請求者名をキーにしてしまうと同一名の請求者が現れた時に問題となる。よって、新たにキーをクラスに付加することが多い。たとえば、請求書クラスには請求書コードという属性を追加するのである。このようにしておいた方が請求書オブジェクトを確実にユニークにする方法として適しており、大量のトランザクションから参照される際にもサイズ面で効率的なものとなる。

2.属性と操作の具体化

クラスを表現するのに重要な属性と操作を記述する。なお、操作については、あまり記述されることはないだろう。操作を考える際のポイントは以下の通りである。

DataManageに必要な操作として検討すべきもの

  1. 自クラスと集約クラスの属性値を加工することで結果を返すような場合。
  2. 集約するクラスを自クラスによって外部から隠蔽するために、集約クラスの操作と同一の操作を自クラスに持つ必要がある場合。

DataManageの操作として不適切、または、クラス図に書き入れる必要のないもの

  1. 自クラスの属性をset、getする操作はクラス図中に明記しなくてよい。(デフォルトで備わっているものと考える)
  2. 複数のクラスが関係するような操作については、DataManageに属するクラスの操作にせず、Processに属するクラスを検討する。

上記2.のような操作をDataManageに属するクラスの操作としてしまうと、システムに対して、大きな制約を設ける可能性がある。なぜなら、システムから操作を呼び出すときに、対象となるDetaManageオブジェクトを探さなければならないからである。また、1個のデータに対して1個のインスタンスが割り付けられるというDataManageの特徴から考えると、システムにとってユニークであるはずの操作がDataManageに属するインスタンスに点在していること自体、矛盾があることがわかるだろう。

従って、このようなサービの決定はProcessレイアのモデリングに委ねられることになる。しかし、時には、Processモデルでもこの操作の確定を避け、設計フェーズまで見送くられることもある。設計段階でDataManageのアクセスポイントを明確にした上で決定することが望ましいと判断された時などがそうである。

3.関連の具体化(クラス図)

クラスの関連について集約、関連名、限定子、多重度、ロールなどの表記オプションを使用することでクラス図の理解度を高める。

sorry this is image
図20-8

クラス図全体を見渡し、参照頻度が多いオブジェクトはできるだけ疎結合となるように関連の方向性を記述する。たとえば、マスタとトランザクションの関係において、トランザクションオブジェクトがマスタオブジェクトを参照していることが分かるように関連に方向性を付けることが重要である。なぜなら、マスタに位置付けられるオブジェクトは、他のシステムやアプリケーションからも再利用されるAppPartsレイア(「第18章 再利用基盤モデル 」の再利用レイア)に属するクラスとなるため、Appに属するクラスを直接的に参照しないように分析当初から配慮する必要があるからだ。

たとえば、顧客マスタクラスと関連する請求書クラスの方向性を図20-9のように示すことで、顧客マスタクラスが請求書クラスを参照しないことが明らかになり、モデルを理解しやすくなる。

sorry this is image
図20-9 関連の方向性

2.4 ストラクチャカードの作成

属性と関連の詳細化を終えたら、抽出されたクラスに対してストラクチャカードを作成する。このドキュメントの特徴は、クラスの役割と責任に加え、クラスの保有する属性を明らかにする目的を持つことである。操作についてはあまり重要とされないが、属性記入欄の後に最小限の操作を記入してもよい。

図20-10にストラクチャカードの記入例を示す。図では、属性の型を明らかにしていないが、クラス図の表記法に基づいて属性の型を記述してもよい。属性欄の「*」は、そのオブジェクトのキーを示す。図の売上伝票クラスでは、「日時」と「売り上げNO」を合わせたものががキーとなる。

sorry this is image
図20-10 ストラクチャカードの記入例

sorry this is image

Processに位置付けられるオブジェクトは、要求を実現するための制御を行うオブジェクトである。Processに属するオブジェクトは、メニュー項目(View)と勘違いされてしまうことが多いようだ。メニューは、ユーザからの指令を受けイベントを発する仕組みであるのに対して、Processに位置付けられるオブジェクトは、そのイベントを受けて実際の処理を実行するオブジェクトである。

請求書発行のシナリオを例に示そう。このシナリオはメニューとProcessオブジェクトの関係を強調するためにやや冗長に記述してある。この中の「請求書管理」というものがProcessに属するオブジェクトで、請求書や売上伝票などはDataManageに属するオブジェクトということになる。請求書管理オブジェクトは請求書発行というメニューからの要求に応じることもできるし、請求書取り消しメニューからの要求に応じることもできる。

請求書の発行

請求書発行というメニュー項目を選ぶと、請求書ダイアログが開く。そこでユーザが発行する顧客と対象月を入力して実行ボタンを押すと、請求書管理に通知される。請求書管理は、月ごとに管理されている売り掛けとなったオブジェクトを集計して請求書を作成する。

メニュー項目をオブジェクトと勘違いしてしまうのは機能を中心として考えてしまうからである。請求書管理オブジェクトは、請求書に関する機能をまとめて管理してくれる便利なオブジェクトである。つまり、Prcoessに属するオブジェクトは制御(機能)中心でありながらも、あくまで機能を束ねた「オブジェクト」という単位を作り出すことに注意しなければならない。

なお、図20-14に上記例題に対するProcessとDataManageを結合したクラス図を示しているので参照してほしい。

3.1 クラスインタフェースの決定

クラスのインタフェースとは、クラスから生成されるオブジェクトを使う上で重要となる一連の操作のことをいう。

1.主要な操作の決定

オブジェクトがシステム要求に対してなんらかの役割を果たすために重要となる最小限の操作を、シネマスコープモデルで見つけたオブジェクトの候補毎に定義してみる。インタフェースとしての操作の個数は5つ程度に押さえるのが望ましい。

操作を実現するためのその他のメソッドについては、おおよその把握をしていることは大切であるが、仕様化の対象にはならない。あくまで、オブジェクトの利用法が分かる操作だけが対象となる。

2.役割による要素分解

ひとつのオブジェクトの持つ役割が意味的に大きい場合は、役割の従属関係や大小関係に注目しながらオブジェクトを分割してみる。分割されたオブジェクトは、元となるオブジェクトとの従属関係が強い場合は集約となり、従属関係が浅い場合は関連という関係となる。

3.シナリオに基づくコラボレーションの検証

シネマスコープモデルによって作成したシナリオを参考に、コラボレーション図(動的構造モデル)を使って実行のシミュレートを行う。ここではコラボレーション図を清書するようなことはせず、以下のような点に着目して何度も試行錯誤を繰り返して操作とオブジェクトの関係が最善の形になるようにクラスの構造を調整する。

  • このオブジェクトの操作として適切か?他のオブジェクトが持つべき操作では?
  • メッセージ伝搬の流れが滞らないか?冗長性はないか?
  • オブジェクトのライフサイクル(生成と消滅)に矛盾を来していないか?

3.2 インタフェースの抽象化

それぞれに異なる役割に対して共通的なインタフェースを作ることは、モデルの理解性を高めることになり、実装フェーズにおいては拡張性や再利用性のある構造を生み出しやすい。役割とインタフェースが密接に関係することから考えると、異なる役割に対して共通的なインタフェースを作るというのは理解性を増すこととは矛盾するように思えるかもしれない。

「共通的なインタフェースを作る」ということは、役割の抽象化と考えることができる。それは、役割を示す文章から共通的な動作を取り出して、その動作で具体的な役割を抽象化するのである。

インタフェースの抽象化は、コンポーネント分析フェーズで対象となるフレームワークの開発などには多用される考え方であるが、問題領域分析フェーズにおいては、使われることはあまりないだろう。

簡単なエージェント・フレームワークを例に説明してみよう。このフレームワークは、ユーザ要求として「いろんな仕事を複数のサーバで行いたい」という以下のような要求を想定して作成されたものと過程する。

  • 複数のサーバに立ち寄って検索条件に合致する顧客情報を取得し、クライアント側に出力したい。
  • 指定されたサーバに行って顧客情報を登録したい。
  • 複数のサーバに立ち寄って顧客情報を更新したい。
  • 今後、顧客情報以外の情報に対しても上記のような処理を行えるようにしたい。

ここでフレームワークとして重要なことは、「サーバ側で行う仕事を、固定してはならない」ということである。仕事の内容はフレームワークを使うアプリケーションによって決められるものでなければならない。

よって、個々の仕事の内容を抽象化したインタフェースを考えなければならない。そこで、複数のサーバで仕事を行う際の共通点に注目してみる。たとえば、以下のような操作を持つJobインタフェースを作成するのである。

表20-1 Jobインタフェースの抽象操作名
インタフェース名[Job]
操作名 操作の内容
exec():boolean サーバ側で実行する仕事
addServer(Worker serverWorker):boolean 実行するサーバを設定する(複数可)
getResult():Set 実行結果のオブジェクト群を取得する

抽象化されたJobインタフェースに従って実際の仕事を行うクラスを、「SelectCustomer」「AddCustomer」「UpdateCustomer」として作成する。これらは、Jobインタフェースを使用するアプリケーションクラスということになる。図20-11にJobインタフェース関連のクラス図を示しておこう。

sorry this is image
図20-11 抽象化されたJobインタフェースとその具象クラス

図20-12にエージェント・フレームワークのクラス図を参考に示す。また、表20-2に簡単なクラスの解説を示す。図20-12で注意すべき点は、Workerクラスは本来サーバ側に配置されることを想定したものであるが、ここではその実現手段を構造として示していない点である。コンポーネント要求のモデルでは、理想のソフトウェア環境を想定している。そのため、クライアント/サーバ間の通信手段を抽象化したのである。このエージェント・フレームワークでは、クライアント/サーバ間の通信に分散オブジェクトを利用することを考えているが、分散オブジェクト製品による具体化なアーキテクチャをモデルに含めず、理想の分散オブジェクト環境を想定したネットワーク透過なモデルとしているのである。

このような抽象化により、エージェント・フレームワークが本来なすべき役割と責任に注目してモデル化することができる。

sorry this is image
図20-12 エージェント・フレームワークの全体像(コンポーネント要求モデル)

表20-2 エージェント・フレームワークのProcessクラス解説
クラス名 説明
Worker サーバ側に存在するクラス。受け取ったAgentを実行し、結果を通知する。
WorkerController サーバにある複数のWorkerを管理しているオブジェクト。
Agent 複数のJobを持ち、サーバ側へ送られる。実行結果を保持する。
Job
(interface)
Jobの基本操作を抽象的なインタフェース化したもの。
ResultListener
(interface)
Agentの実行結果(Agent自身)通知を受け取るための操作を持つインタフェース。

2.3 インタフェースカードの作成

クラスのインタフェースが定まってきた段階でインタフェースカードを作成する。このドキュメントの特徴は、クラスの役割と責任に加え、クラスの保有する代表的な操作を明らかにする目的を持つことである。 図20-13にインタフェースカードの記入例を示す。

sorry this is image
図20-13 インタフェースカードの記入例

sorry this is image

PD結合とは、ProcessのモデルとDataManageのモデルを結合して要求モデルにすることである。図20-14は、一連の例として取り上げてきた請求書発行システムをPD結合した図である。この図のように、Processに属するクラスとDataManageに属するクラスの間の関係は、この段階では関連より弱い依存関係にしておいた方がよいかもしれない。なぜなら、ProcessクラスはDataManageクラスを操作する際、多くのDataManageクラスと複雑に関係を持ってしまうかもしれないが、その関係は関連ほど強くないように実装することが多いからである。具体的に言うと、Processクラスのメソッド内容は、Viewの要求に対応してDataManageオブジェクトをデータベース等から取得し、何らかの処理を行った後、結果をViewに返すというパターンが多いからである。

また、Viewは、図のようにクラス化されないまま記述される。Viewに属するクラスは、アーキテクチャモデルにて詳細化される。しかし、図のように丸いオブジェクトとして表しておくことで、Processに属するクラスの役割が分かりやすくなる。

sorry this is image
図20-14 ViewとProcessの統合(請求書発行)


*begin*back*foward*end*contents

この記事のトップへ