オブジェクト指向を使った設計: ソフトウェア開発プロセス JavaとUMLで学ぶオブジェクト指向の考え方 第6章 オブジェクト指向を使った設計: ソフトウェア開発プロセス 2003年7月3日(木) 荒木研究室 学部四年 三好 健吾
この章のポイント オブジェクト指向的な設計プロセス クラス発見プロセスの開始 役割とコラボレーションの識別プロセスの開始
6.1 設計のガイドライン 優れたシステムの設計方法(1) システム・・・互いに対話するクラス 今日では多くの設計手法が語られている 6.1 設計のガイドライン 優れたシステムの設計方法(1) システム・・・互いに対話するクラス 今日では多くの設計手法が語られている どの方法論を使用するかではなく、単に方法論を 使用するかどうかということが重要 ・・・ソフトウェア開発プロセス全体に共通の問題 優れた設計を行うには、設計者とその組織が満足 できるプロセスを見つけることが最も重要
優れたシステムの設計方法(2) 通常の確かなオブジェクト指向設計プロセスに 含まれる手順 ・適切な分析を行う 含まれる手順 ・適切な分析を行う ・システムを記述する作業明細を作成する ・作業明細から用件を収集する ・ユーザーインターフェイスのプロトタイプを作成する ・クラスを識別する ・各クラスの役割を決定する ・クラス間の対話方法を決定する ・構築するシステムを記述する高水準のモデルを作成する
フェーズの境界を越える反復を最小限に抑えることが重要 優れたシステムの設計方法(3) 出来るだけ多くの 問題を把握する 設計 設計フェーズでは、用件と設計の変更にかかるコストが比較的低い 実装フェーズでは、設計の変更にかかるコストがかなり高い 導入フェーズでは、設計の変更にかかるコストが天文学的になる 非常に高い コスト 実装 ? 導入 ? ? ユーザーが真に望まないソフトウェア フェーズの境界を越える反復を最小限に抑えることが重要
優れたシステムの設計方法(4) ソフトウェアのリリース後はリリース前に把握して修正出来なかった問題を解決するコストが更に増大 リコール問題が発生すると、修理コストが多額になるだけで なく、企業の評判が傷つく パッケージ2 低品質 不十分なサポート パッケージ1 高品質 充実したサポート 競争力
設計プロセスについて(1) 適切な分析 作業明細(statement of work) 分析フェーズでは、ユーザーと開発者が適切な調査と分析によって作業明細とプロジェクト用件を確定し、本当にそのプロジェクトを実行に移すかどうかを判断する 作業明細(statement of work) ・システムを記述するテキスト文書 目的 : 読む人全員にシステムを完全に理解させること ・作業明細にはシステムについて必要な情報を全て記載する
設計プロセスについて(2) 用件の収集 ユーザーインターフェイスのプロトタイプの開発 クラスの識別 要求仕様 ・ユーザーが求めるシステム機能を記載 ・箇条書きの各項目はシステムの特定の用件を示し、要件は 作業明細から作成する ユーザーインターフェイスのプロトタイプの開発 ・プロトタイプの作成・・・ユーザーと開発者がシステムを理解して いることを確認する最も良い方法の一つ クラスの識別 ・要件からクラスを識別する方法 : 全て名詞に注目すること
設計プロセスについて(3) 各クラスの役割の決定 クラス間の対話方式の決定 システムを記述するクラスモデルの作成 ・識別した各クラスの役割(責任範囲)を決定する必要がある クラス間の対話方式の決定 ・各クラスの役割を果たすために、他のクラスと何度も対話する 必要がある ・・・ メッセージの送信 システムを記述するクラスモデルの作成 ・システム全体を表すクラスモデルを構築する ・クラスモデルは、システム内の様々なクラスが互いに対話する様子を示す
6.2 ブラックジャックの例 最終的にはクラス、その役割、およびコラボレーションを発見する <基本的な目標> ブラックジャックをシュミレートするソフトウェアシステムを設計すること (やろうとしていうのはゲームの実装方法ではなくシステムの設計) 最終的にはクラス、その役割、およびコラボレーションを発見する
システム用件の考え方 ユーザーの観点で考える ・実装を考える必要はなく、インターフェイスに焦点を当てる ・実装を考える必要はなく、インターフェイスに焦点を当てる ・システムがいかに動作するかではなく、何を行うかについて考える必要がある (第1章「オブジェクト指向のコンセプト」のブラックボックスの例など)
CRCカードの使用 CRC(Class-Responsibility-Collaboration)カード クラス:クラス名 役割: コラボレーション: CRC(Class-Responsibility-Collaboration)カード ・クラスを識別して分類する最も 一般的な方法の一つ ・各カードが1つのクラスの データ属性、役割、および コラボレーションを表す CRCカードのフォーマット
ブラックジャックのクラスの識別(1) 一般に、クラスは名詞に相当 (但し、名詞が必ずクラスになるとは限らない) <手法> (但し、名詞が必ずクラスになるとは限らない) <手法> 要求仕様から名詞を抽出 その他オブジェクト(クラス)として考えられるものをリストアップ 各クラスについて検討 最終的なクラスを決定
ブラックジャックのクラスの識別(2) オブジェクト(クラス)として考えられるもの ゲーム カード(複数形) エース ブラックジャック カード ロイヤルカード ディーラー 山 キング ハウス 手札 クイーン プレーヤー(複数形) カードの数値 賭け金 プレーヤー スート
ブラックジャックのクラスの識別(3) ブラックジャックの最初のクラス ゲーム カード(複数形) エース ブラックジャック カード ロイヤルカード ディーラー 山 キング ハウス 手札 クイーン プレーヤー(複数形) カードの数値 賭け金 プレーヤー スート ブラックジャックの最初のクラス
クラスの役割の識別(1) 役割は動詞に関連する 要求仕様から動詞を選択することで役割を識別できる 但し、以下の点に注意 要求仕様から動詞を選択することで役割を識別できる 但し、以下の点に注意 ・要求仕様にある全ての動詞が最後まで役割として残るわけではない ・実際の役割を見つけるために、いくつかの動詞を結合する場合が ある ・元の要求仕様には含まれていない役割が最終的に選択される 場合がある ・役割の識別は繰り返し行う為、要求仕様と役割の両方を継続的に 改訂し更新する必要がある ・2つ以上のクラスが役割を共有する場合は、各クラスにその役割を 割り当てる
クラスの役割の識別(2) <手法> クラスの役割を明らかにするため、要求仕様から動詞を抽出 その他各クラスについて、考えられる役割をリストアップ 各役割について検討 最終的な役割を決定
クラスの役割の識別(3) 『カード』クラスの役割 カードの数値を知る ・・・ カードの数値の掲示 スートを知る ・・・ 名前の掲示 カードの数値を知る ・・・ カードの数値の掲示 スートを知る ・・・ 名前の掲示 絵札であるかどうかを判定する エースであるかどうかを判定する ジョーカーであるかどうかを判定する
クラスの役割の識別(4) 『山』クラスの役割 シャッフルする 次のカードを配る 山に残っているカードの枚数を数える ゲームの開始時に全てのカードが山にあることを確認する
クラスの役割の識別(5) 『手札』クラスの役割 手札の枚数を数える ・・・ 手札の枚数の報告 手札の値を知る ・・・ 手札の値の報告
クラスの役割の識別(6) 『ディーラー』クラスの役割 カードを配る 勝者を判定する 新しいゲームを開始する 山をシャッフルする カードを配る 勝者を判定する 新しいゲームを開始する 山をシャッフルする プレーヤーにカードを渡す ディーラーの手札を見せる ディーラーの手札の値を計算する ・・・ ディーラーの手札の値の掲示 ディーラーの手札の枚数を数える ・・・ ディーラーの手札の枚数の掲示 カードを要求する(ヒットまたはホールド)
クラスの役割の識別(7) 『プレーヤー』クラスの役割 カードを要求する(ヒットまたはホールド) プレーヤーの手札を見せる プレーヤーの手札の値を計算する ・・・ プレーヤーの手札の値の掲示 手札の枚数を数える ・・・ プレーヤーの手札の枚数の掲示 手札のが21(ブラックジャックを含む)、 20以下、または22以上である ことを判定する ・・・ 手札の値の報告
クラスの役割の識別(8) 『賭け金』クラスの役割 設計プロセスを繰り返した結果 独立した『賭け金』クラスは不要 賭ける対象の種類を判定する 現在の賭け金額を知る プレーヤーの所持金の残高を知る 賭け金を出せるだけの所持金があるかどうかを判定する 設計プロセスを繰り返した結果 独立した『賭け金』クラスは不要
クラスの役割の識別(9) そのクラスが必要かどうか判断する点 現在そのクラスが本当に必要かどうか、あるいは、将来必要になりそうか システムの設計を大幅に変更することなく、そのクラスを将来簡単に追加できるかどうか
UMLユースケース: コラボレーションの識別(1) コラボレーションを識別するためには、役割を検討し、オブジェクトがどのクラスと対話するかを判断する必要がある = オブジェクトが全ての役割を果たし、仕事を完了するために 必要な他のクラスを識別する コラボレーションについて考えている時に、必要なクラスを忘れていたり、最初に想定した一部のクラスが必要なかったことを発見する場合がある
UMLユースケース: コラボレーションの識別(2) コラボレーションを見つけるには、ユースケースのシナリオを利用できる ユースケース・・・ユーザーの要求やイベントに応答して システムが実行するトランザクション (一連の関連する動作) ユースケースごとに、オブジェクトとそれらが交換するメッセージを識別する コラボレーション図を作成して、この手順を文書化できる
UMLユースケース: コラボレーションの識別(3) ユースケースのシナリオを作成する真の目的は、不必要なクラスと役割を除去すること コラボレーションの検討によって忘れていた必要なクラスを発見したり、最初選択したが思ったほど必要でないクラスが判明したりする場合がある。 必要なクラスを発見・・・簡単にCRCカードを追加できる 不要なクラスを発見・・・CRCカードを削除し、 検討の対象から外す CRCカードはクラスの発見に、ユースケースシナリオはコラボレーションの発見に役立つ
UMLユースケース: コラボレーションの識別(4) ある一つのシナリオを考える(別紙資料参照) この最初の設計におけるコラボレーション図(1) 新しいゲームを開始 アプリケーション ディーラー ゲームを開始する
UMLユースケース: コラボレーションの識別(5) この最初の設計におけるコラボレーション図(2) 山をセット ディーラー 山 山をシャッフル ディーラー 山 カードを追加 ディーラー プレーヤー 値を返す シャッフルして最初の手札を配る
UMLユースケース: コラボレーションの識別(6) この最初の設計におけるコラボレーション図(3) 手札の値を取得 プレーヤー 手札 値を返す 手札の値を取得する カードを要求 ディーラー 山 カードを返す カードを取得する
UMLユースケース: コラボレーションの識別(7) この最初の設計におけるコラボレーション図(4) カードを返す ディーラー プレーヤー プレーヤーは破産したか ディーラー プレーヤー 値を返す カードを配り、プレーヤーが破産したかどうかをチェックする
UMLユースケース: コラボレーションの識別(8) この最初の設計におけるコラボレーション図(5) 手札の値を要求 プレーヤー 手札 値を返す 手札の値を返す カードを追加 ディーラー (プレーヤー) ディーラー 値を返す 手札の値を取得 ディーラー (プレーヤー) 手札 値を返す ディーラーは新しいカードを要求するか?
UMLユースケース: コラボレーションの識別(9) この最初の設計におけるコラボレーション図(6) カードを要求 ディーラー (プレーヤー) ディーラー カードを返す カードを渡す ディーラー 山 要求に応じてディーラーにカードを渡す
UMLユースケース: コラボレーションの識別(10) この最初の設計におけるコラボレーション図(7) 手札の値を取得 ディーラー (プレーヤー) ディーラー 値を返す 手札の値を取得 ディーラー (プレーヤー) 手札 値を返す ディーラーまたはプレーヤーがスタンドしたか?
CRCカードの初期状態(1) 最初のクラスとコラボレーションを識別したので、各クラスのCRCカードを完成させることが出来る ただし、これらのカードが単に初期段階の状態に過ぎないことに留意 最終的にリストに残るクラスとコラボレーションは、最初の状態と大きく異なる可能性がある
CRCカードの初期状態(2) カードクラスのCRCカード 山クラスのCRCカード クラス:カード 役割: コラボレーション: 名前を取得 山 役割: コラボレーション: 名前を取得 山 値を取得 クラス:山 役割: コラボレーション: 山をリセット ディーラー 山のサイズを取得 カード 次のカードを取得 山をシャッフル 山を掲示 カードクラスのCRCカード 山クラスのCRCカード
CRCカードの初期状態(3) ディーラークラスのCRCカード プレーヤークラスのCRCカード クラス:ディーラー 役割: コラボレーション: 役割: コラボレーション: 新しいゲームを開始 手札 カードを取得 プレーヤー 山 クラス:プレーヤー 役割: コラボレーション: カードを要求 手札 カードを取得 ディーラー 手札を掲示 手札の値を取得 ディーラークラスのCRCカード プレーヤークラスのCRCカード
CRCカードの初期状態(4) 手札クラスのCRCカード クラス:ハンド 役割: コラボレーション: 値を返す プレーヤー カードを追加 役割: コラボレーション: 値を返す プレーヤー カードを追加 ディーラー 手札を掲示 手札クラスのCRCカード
UMLクラス図:オブジェクトモデル(1) CRCカードを使って最初の設計を完了したら、CRCカードに記載されている情報をクラス図に移す クラス図=あり得る設計例 クラスの最初の課題を表しているのではない
UMLクラス図:オブジェクトモデル(2) Hand Player Deck -value:int Limit:int -hand:Vector +getValue:int +addToHand:void +showHand:void Player Limit:int Player: +moreCards:boolean +getCard:void +showHand:void +getValueOfHand:void Deck -Cards:Vector -shuffledCards:Vector random:Random -nextItem:int Deck: +resetDeck:void +getDeckSize:int getNextCard:Card +shuffleDeck:void showOriginalDeck:void +completeDeck:void -createHearts:void -createSpades:void -createClubs:void -createDiamonds:int Card -Name:String -Value:int -Suit:String +getName:String +getValue:int +getSuit:String +setName:void +setValue:void +setSuit:void Dealer startNewGame:void +getCard:Card
ユーザーインターフェイスのプロトタイピング ユーザーインターフェイスのプロトタイプの作成 オブジェクト指向設計プロセスの最後の手順 プロトタイプを作成することで設計の反復プロセスに役立つ貴重な情報を得ることが出来る プロトタイプの作成方法 ・ユーザーインターフェイスの概略を紙やホワイトボードに書く ・プロトタイピング専用のツールを使用 ・Visual Basic等の言語環境を用いる ・使い慣れた開発ツールのIDEを用いる
6.3 まとめ この章では、システム全体の設計プロセスについて説明した 6.3 まとめ この章では、システム全体の設計プロセスについて説明した ここでは、複数のクラスを統合して、システムにまとめ上げることに焦点を当てた