ガイドライン: 分析クラス
トピック
分析クラスには次のような種類のステレオタイプがあります。
- バウンダリー・クラス
- コントロール・クラス
- エンティティー・クラス
クラスを探す際の具体的なプロセス ・ガイダンスとなるだけでなく、ステレオタイプ化することで、モデルを変更しても特定の範囲しか影響を受けない堅牢なオブジェクト・モデルができます。例えば、ユーザー・インターフェースを変更しても、影響を受けるのはバウンダリー・クラスだけです。制御フローを変更しても、コントロール・クラスに影響があるだけです。長期保存情報に変更があっても、エンティティー・クラスに影響があるだけです。ただし、このようなステレオタイプ化が特に役に立つのは、分析と初期設計においてクラスを識別する場合です。普通、設計フェーズの後半では、少し異なる構成のステレオタイプを使って、実装環境やアプリケーション・タイプなどとのよりよい対応付けを検討することが必要になります。
バウンダリー・クラスは、システムの周辺要素と内部動作の間の相互作用をモデル化するために使用するクラスです。このような相互作用には、イベントの変換と解釈、システム表現 (インターフェースなど) の変更の認識が関連します。
バウンダリー・クラスは、周囲の環境に依存するシステムの部分をモデル化します。エンティティー・クラスとコントロール・クラスは、システムの周辺環境に依存しない部分をモデル化します。このように、GUI や通信プロトコルの変更は、エンティティー・クラスやコントロール・クラスには関係なく、バウンダリー・クラスの変更だけを意味していなければなりません。
また、バウンダリー・クラスによってシステムの境界が明確になるので、システムの理解も容易になります。バウンダリー・クラスは関連するサービスを識別するためのよい出発点になり、設計の助けになります。例えば、設計の初期段階でプリンター・インターフェースが識別されたなら、印刷物の形式もモデル化する必要があることがすぐにわかります。
一般的なバウンダリー・クラスには、ウィンドウ、通信プロトコル、プリンター・インターフェース、センサー、端末などがあります。ボタンのような決まったインターフェース部品を独立したバウンダリー・クラスとしてモデル化する必要はありません。一般に、ウィンドウ全体が最も小さな単位のバウンダリー・オブジェクトです。バウンダリー・クラスは、古いレガシー・コードのような非オブジェクト指向 API へのインターフェースの取得にも役立ちます。
表現する境界 (バウンダリー) の種類に従って、バウンダリー・クラスをモデル化する必要があります。別のシステムとのコミュニケーションと、人間のアクターとのコミュニケーション (ユーザー・インターフェースを通じた) では、目的が大きく異なります。人間のアクターとのコミュニケーションの場合、最も重要な考慮事項は、ユーザーに対してインターフェースを提示する方法です。別のシステムとのコミュニケーションにおいて最も重要な考慮事項は、通信プロトコルです。
バウンダリー・オブジェクト (バウンダリー・クラスのインスタンス) は、例えば 2 つのユース・ケースの実行のあいだ画面上に表示されなければならない場合には、ユース・ケースのインスタンスより長く存在していることがあります。しかし、通常は、バウンダリー・オブジェクトの寿命はユース・ケースのインスタンスと同じです。
バウンダリー・クラスの発見
バウンダリー・クラスはシステム外のものへのインターフェースの仲立ちをします。
バウンダリー・オブジェクトは、周囲の変更 (他のシステムへのインターフェースの変更、ユーザー要求の変更など) からシステムを遮断し、このような変更がシステムの他の部分に影響を与えないようにします。
1 つのシステムが、複数の種類のバウンダリー・クラスを持つことができます。
- ユーザー・インターフェース・クラス: システムの人間ユーザーとの通信を仲立ちするクラス
- システム・インターフェース・クラス: 他のシステムとのコミュニケーションを仲立ちするクラス
- デバイス・インターフェース・クラス: 外部イベントを検出するデバイスへのインターフェースを提供するクラス (センサーなど)
ユーザー・インターフェース・クラスの発見
ユース・ケースとアクターの各ペアに対して、1 つのバウンダリー・クラスを定義します。このクラスは、アクターとの相互作用を調整する責務を持っているものと考えられます。主バウンダリー・クラスが責務の一部を委任する補助クラスを表すため、さらに追加してバウンダリー・クラスを定義することもできます。
これはウィンドウ・ベースの GUI アプリケーションの場合に特に当てはまり、ウィンドウまたはフォームごとに 1 つのバウンダリー・オブジェクトをモデル化できます。システムの中心となる抽象概念のみモデル化します。GUI のボタン、リスト、ウィジェットをすべてモデル化してはいけません。分析の目標はシステムの構成方法の全体図を作ることであって、システムの細部まで漏れなく設計することではありません。言い換えると、システム内の現象についてのみ、または分析ユース・ケースの実現のイベント・フローで取り上げられていることについてのみ、バウンダリー・クラスを明確にします。
スケッチを描くか、またはユーザー・インターフェースのプロトタイプのスクリーン・ダンプを使用して、バウンダリー・オブジェクトの振る舞いや体裁を示します。
システム・インターフェース・クラスの発見
外部システムと通信するバウンダリー・クラスには、外部システムとの対話を管理する責務があります。このクラスは、外部システムに対するインターフェースを構築中のシステムに提供します。
例
ATM では、お金の引き出し操作はアクターである「ATM ネットワーク」を通じて検証する必要があります (このアクターはこの引き出し操作を銀行の会計システムで確認します)。「ATM ネットワーク」とのコミュニケーションを行うために、「ATM ネットワーク・インターフェース」という名前のオブジェクトを識別できます。
既存システムへのインターフェースは、既に定義が済んでいる可能性があります。その場合は、インターフェース定義から責務を直接抽出する必要があります。
正式なインターフェース定義が存在している場合は、リバース・エンジニアリングが可能であり、ここでインターフェースを正式に定義する必要はありません。設計の際には既存のインターフェースを再利用するということを記録してだけおきます。
デバイス・インターフェース・クラスの発見
システムには、センサー機器のように、あたかも外部に存在するかのように振る舞う (システム内のオブジェクトが影響を与えなくても自発的に値を変える) 要素が存在する場合があります。この種の外部デバイスはアクターで表現できますが、デバイスと人間のアクターを同じ「レベル」に置くことになり、システムのユーザーにとっては「混乱」のもとになります。しかし、要求の収集からいったん距離をおき、すべての外部イベントのソースを検討して、システムがこのようなイベントを検出できるようにする必要があります。
ユース・ケース・モデル内でデバイスがアクターとして表現されていれば、バウンダリー・クラスを使ってデバイスとシステムの間のコミュニケーションを仲介することはきわめて当然のことです。ユース・ケース・モデルにこのような「デバイス・アクター」がない場合は、この時点で追加するのが適切であり、必要に応じてユース・ケースの補足説明を更新します。
「デバイス・アクター」ごとにバウンダリー・クラスを作成し、デバイスまたはセンサーの責務を把握します。デバイスに対するインターフェースが既に適切に定義されている場合は、そのことをメモして後で設計中に参照できるようにします。
コントロール・クラス は、1 つまたは数個のユース・ケースに特有な、制御の振る舞いをモデル化するために使用するクラスです。多くの場合、コントロール・オブジェクト (コントロール・クラスのインスタンス) は他のオブジェクトを制御するので、振る舞いは調整タイプのものになります。コントロール・クラスは、ユース・ケース特有の振る舞いをカプセル化します。
コントロール・オブジェクトの振る舞いは、特定のユース・ケースの実現と深くかかわっています。多くのシナリオでは、コントロール・オブジェクトが分析ユース・ケースの実現を「実行」しているとも言えます。ただし、ユース・ケース同士の関連性が強い場合には、2 つ以上の分析ユース・ケースの実現にかかわるコントロール・オブジェクトも出てきます。さらに、異なるコントロール・クラスの複数のコントロール・オブジェクトが 1 つのユース・ケースに参加することも可能です。コントロール・オブジェクトを必要としないユース・ケースもあります。例えば、ユース・ケース内のイベント・フローが 1 つのエンティティー・オブジェクトと関連している場合、バウンダリー・オブジェクトはこのエンティティー・オブジェクトと共同でユース・ケースを実現できます。分析ユース・ケースの実現ごとに 1 つのコントロール・クラスを識別することから始め、分析ユース・ケースの実現の数が増えて共通点が発見されたなら、コントロール・クラスを修正して洗練させます。
コントロール・クラスは、システムの動的な性質を表し、主要なタスクと制御フローを扱っているので、システムの理解に役立ちます。
システムがユース・ケースを実行するときには、コントロール・オブジェクトが 1 つ作成されます。ユース・ケースの実行が終わると、通常、対応するコントロール・オブジェクトの寿命も終わります。
コントロール・クラスがユース・ケースで必要なすべてのことを行っているわけではないことに注意してください。コントロール・クラスは、実際には、機能を実装する他のオブジェクトの作業を調整しています。コントロール・クラスは、機能の責務を割り当てられているオブジェクトに作業を委任します。
コントロール・クラスの発見
コントロール・クラスは、システム内の調整的振る舞いを提供します。システムは、コントロール・オブジェクトがなくてもユース・ケースを実行できる場合があります (エンティティー・オブジェクトとバウンダリー・オブジェクトだけを使います)。特に、格納情報を単に操作するだけのユース・ケースの場合がそうです。
ユース・ケースがさらに複雑になると、一般に、1 つ以上のコントロール・クラスを使って、システム内の他のオブジェクトの振る舞いを調整する必要があります。コントロール・オブジェクトの例としては、トランザクション・マネージャー、リソース・コーディネーター、エラー・ハンドラーなどのプログラムがあります。
コントロール・クラスは、バウンダリー・オブジェクトとエンティティー・オブジェクトを効果的に切り離すので、システムはシステム境界での変更による影響を受けにくくなります。また、コントロール・クラスはユース・ケース特有の振る舞いをエンティティー・オブジェクトから切り離すので、ユース・ケース間やシステム間でのエンティティー・オブジェクトの再利用性が向上します。
コントロール・クラスが提供する振る舞いには、次のような特徴があります。
- 周囲から独立している (周囲が変化しても変わらない)。
- ユース・ケース内の制御ロジック (イベント間の順序) とトランザクションを定義している。
- エンティティー・クラスの内部構造や振る舞いが変化してもほとんど変わらない。
- 複数のエンティティー・クラスのコンテンツを使用または設定するので、これらのエンティティー・クラスの振る舞いを調整する必要がある。
- 起動のたびにいつも同じ動作を実行するわけではない (イベント・フローに複数の状態がある)。
コントロール・クラスの必要性の判断
ユース・ケースのイベント・フローでは、さまざまな作業を実行する順序を定義します。既に識別されているバウンダリー・クラスとエンティティー・クラスでフローを処理できるかどうかの調査から始めます。主に情報の入力、検索と表示、修正などを行う単純なイベント・フローの場合は、普通、コントロール・クラスを別に作成する必要はありません。バウンダリー・クラスがユース・ケースの調整を行います。
イベント・フローを独立したコントロール・クラスにカプセル化する必要があるのは、コントロール・クラスが複雑で、システムのインターフェース (バウンダリー・クラス) または格納情報 (エンティティー・クラス) とは独立に変化する動的振る舞いがある場合です。イベント・フローをカプセル化することで、異なるインターフェースや異なる格納情報 (または少なくとも異なる下位データ構造) を持つ各種システムに対し、潜在的に同一のコントロール・クラスを再利用できるようになります。
例: タスク・キューの管理
「倉庫処理システム」の「タスク実行」ユース・ケースからコントロール・クラスを 1 つ識別できます。このコントロール・クラスはタスクのキューを処理し、タスクが正しい順序で実行されることを保証します。このコントロール・クラスは、適切な運搬機器の割り当てが済めば直ちに、キューから次のタスクを取り出して実行します。したがって、システムは複数のタスクを同時に実行できます。
このコントロール・クラスを「タスク実行者」と「キュー・ハンドラー」という 2 つのコントロール・クラスに分割すれば、対応するコントロール・オブジェクトによって定義される振る舞いの説明がより簡単になります。「キュー・ハンドラー」オブジェクトは、キューの順序と運搬機器の割り当てだけを処理します。キュー全体で 1 つの「キュー・ハンドラー」が必要です。システムは、タスクを実行すると直ちに新しい「タスク実行者」オブジェクトを作成し、これがタスクを実行します。このように、システムが実行するタスクごとに 1 つの「タスク実行者」のオブジェクトが必要になります。

複雑なクラスは、責務の類似性で分割する必要があります。
このような分割を行う主な利点は、キュー処理の責務 (多数のユース・ケースに一般的なもの) と、特定のユース・ケースに固有のタスク管理作業とを分離することにあります。
これにより、設計が進んでも、クラスを容易に理解し、適合させることができます。また、作業負荷を処理するために必要な数のタスク実行者を作成できるので、システムの負荷バランス処理に関しても利点があります。
主イベント・フローと代替/例外イベント・フローの、異なるコントロール・クラスへのカプセル化
変更を簡単にするため、主要なイベント・フローと代替/例外イベント・フローは、異なるコントロール・クラスにカプセル化します。代替フローと例外フローが完全に独立している場合は、これらも同様に分離します。これにより、システムの長期的な拡張と保守がより簡単になります。
2 つのアクターが同じコントロール・クラスを共有している場合のコントロール・クラスの分割
複数のアクターが同じコントロール・クラスを使用している場合は、コントロール・クラスも分割する必要があります。こうすることで、1 つのアクターの要求に対する変更を、システムの他の部分から切り離すことができます。変更のコストが高くついたり、非常に重要な場合は、複数のアクターと関連があるすべてのコントロール・クラスを明らかにして、分割する必要があります。理想的には、各コントロール・クラスは、1 つのアクターと相互作用するか (何らかのバウンダリー・オブジェクトを介して)、またはどのアクターとも相互作用しないようにする必要があります。
例: 通話管理
「市内通話」ユース・ケースを検討します。まず、呼び出し自体を管理するコントロール・クラスを明確にします。

電話システムにおいて市内通話を処理するコントロール・クラスは、関係するアクターごとに「振る舞い A」と「振る舞い B」という 2 つのコントロール・クラスに簡単に分割できます。
市内通話には 2 つのアクターがあります。呼び出しを行う「加入者 A」と、呼び出しを受ける「加入者 B」です。
「加入者 A」は、受話器を取り上げ、発信音を聞き、電話番号をダイヤルします。システムは、この電話番号を保存して分析します。システムは、この電話番号を保存して分析します。システムは、すべての電話番号を受け取ると、「加入者 A」に呼び出し音を聞かせ、「加入者 B」に呼び出し信号を送ります。「加入者 B」が応答すると、呼び出し音と呼び出し信号が止まり、加入者間の会話が始まります。両方の加入者が受話器を置くと、通話は終了します。
2 つの振る舞いを制御する必要があります。つまり、「加入者 A」の側で起きていること、「加入者 B」の側で起きていることです。そのため、元のコントロール・オブジェクトを「振る舞い A」と「振る舞い B」の 2 つに分割しました。
次の場合には、コントロール・クラスを分割する必要はありません。
- コントロール・クラスのオブジェクトと関連しているアクターの振る舞いが決して変化しない、またはほとんど変化しないと十分に確信できる。
- コントロール・クラスのオブジェクトのあるアクターに対する振る舞いが、別のアクターに対する振る舞いと比べてほとんど意味がない (1 つのオブジェクトですべての振る舞いを保持できる)。このような振る舞いの組み合わせであれば、変更可能性に対する影響はほとんどありません。
エンティティー・クラスは、保存する必要のある情報と関連する振る舞いをモデル化するために使用するクラスです。エンティティー・オブジェクト (エンティティー・クラスのインスタンス) を使用して、イベント、人物、現実のオブジェクトのようなある種の現象についての情報の保持と更新を行います。エンティティー・オブジェクトは通常永続的で、システムの存続期間のような長期間にわたって必要な属性と関係を保持しています。
エンティティー・オブジェクトは、通常、1 つの分析ユース・ケースの実現に特有のものではなく、システム自体に固有のものでさえない場合もあります。多くの場合、エンティティー・オブジェクトの属性と関係の値は、アクターによって与えられます。エンティティー・オブジェクトは、システムの内部作業の実行支援に必要な場合もあります。エンティティー・オブジェクトの振る舞いは、他のオブジェクト・ステレオタイプの振る舞いと同じくらい複雑になることがあります。ただし、他のオブジェクトとは異なり、エンティティー・オブジェクトの振る舞いは、エンティティー・オブジェクトが表す現象と強い関連性を持っています。エンティティー・オブジェクトは環境 (アクター) から独立しています。
エンティティー・オブジェクトは、開発中のシステムの中心となる概念を表します。
銀行システムにおけるエンティティー・クラスの典型的な例は、「口座」と「顧客」です。ネットワーク処理システムの例では、「ノード」と「リンク」があります。
モデル化したい現象が他のクラスで使用されていない場合は、エンティティー・クラスの属性としてモデル化することができ、エンティティー・クラス間の関連としてモデル化することさえ可能です。一方、その現象が設計モデルの他のクラスで使用されている場合は、クラスとしてモデル化する必要があります。
エンティティー・クラスは、システムを理解するためのもう 1 つの視点を提供します。これは、エンティティー・クラスが論理データ構造を示しているためであり、システムがユーザーに提供しようとしているものを理解するのに役立ちます。
エンティティー・クラスの発見
エンティティー・クラスは、システム内に保存されている情報を表します。通常は、システムが管理する主要概念を表すために使用されます。エンティティー・オブジェクトは、受動的で永続的であることがよくあります。主要な責務は、システム内に情報を格納して管理することです。
エンティティー・クラスの着想の源としてよく使われるのが、用語集 (要求フェーズで作成) とビジネス ・ドメイン・モデル (ビジネス・モデリングを実施する場合、ビジネス・モデリングで作成) です。
次のものが許可されます。
- 2 つのバウンダリー・クラス間のコミュニケーション関連。例えば、特定のウィンドウが他のバウンダリー・オブジェクトとどのように関連するのかを記述するために使用します。
- バウンダリー・クラスからエンティティー・クラスへのコミュニケーション関連または通知予約関連。バウンダリー・オブジェクトでは、バウンダリー・オブジェクト内のアクション間で特定のエンティティー・オブジェクトを追跡したり、エンティティー・オブジェクト内の状態変化の通知を受けたりすることが必要になる場合があるため、これらの関連を使用します。
- バウンダリー・クラスからコントロール・クラスへのコミュニケーション関連。バウンダリー・オブジェクトが特定の振る舞いをトリガーするために使用します。
次のものが許可されます。
- コントロール・クラスとエンティティー・クラスの間のコミュニケーション関連または通知予約関連。コントロール・オブジェクトでは、コントロール・オブジェクト内のアクション間で特定のエンティティー・オブジェクトを追跡したり、エンティティー・オブジェクト内の状態変化の通知を受けたりすることが必要になる場合があるため、これらの関連を使用します。
- コントロール・クラスとエンティティー・クラスの間のコミュニケーション関連。起動された振る舞いの結果を環境に通知するために使用します。
- コントロール・クラス間のコミュニケーション関連。より複雑な振る舞いパターンを作成するために使用します。
エンティティー・クラスは、他のエンティティー・クラスに対してだけ関連 (コミュニケーションまたは通知予約) のソースとなります。エンティティー・クラスのオブジェクトの寿命は、長くなることがよくあります。一方、コントロール・クラスとバウンダリー・クラスのオブジェクトは、短命になる傾向があります。アーキテクチャーの観点から見ると、外部に対するエンティティー・オブジェクトの可視性を制限するのはよいことです。そうすることで、システムはより変更しやすくなります。
から\へ (誘導可能性) |
バウンダリー |
エンティティー |
コントロール |
バウンダリー |
コミュニケーション |
コミュニケーション 通知予約 |
コミュニケーション |
エンティティー |
|
コミュニケーション 通知予約 |
|
コントロール |
コミュニケーション |
コミュニケーション 通知予約 |
コミュニケーション |
関連ステレオタイプの有効な組み合わせ
- 新しい振る舞いを識別するときは、類似の責務を持つ既存クラスがないかどうかチェックし、可能であればクラスを再利用します。
その振る舞いを実行できる既存のオブジェクトが存在しないことが確かな場合にだけ、新しいクラスを作成します。
- クラスを識別するときは、クラスを調べて一貫した責務を持つことを確認します。
1 つのクラスに関係のない責務が含まれている場合は、オブジェクトを 2 つ以上のクラスに分割します。それに応じて相互作用図を更新します。
- 関係のない責務を見つけてクラスを分割したら、そのクラスがロールを果たすコラボレーションを調べて、コラボレーションの更新が必要かどうかを判定します。必要に応じてコラボレーションを更新します。
- クラスに責務が 1 つしかなくてもそのこと自体は問題ではありませんが、そのクラスがなぜ必要なのかという問題を提起する必要があります。すべてのクラスの存在を吟味して正当性を確認するようにします。
|