*begin*back*foward*end*contents

開発フェーズ編 -
第27章 コンポーネント設計・実装

27.1 目的

コンポーネント設計・実装フェーズでは、個々のコンポーネントについてコンポーネント分析で決定した設計方針に基づいた設計・実装を行う。

27.2 作業ドキュメント

コンポーネント設計・実装で作成するドキュメントの一覧を示す。

ドキュメント名 解説 様式番号
コンポーネントリファレンス コンポーネントとして公開するメソッドの使い方を解説する。 6-01
テスト項目表 コンポーネントをテストする項目の一覧 6-02

27.3 作業項目の解説

コンポーネント設計・実装フェーズでは、コンポーネント分析フェーズによって作成されたコンポーネント要求モデルをベースに、コンポーネントを構成するクラスの構造を詳細化するための設計をおこなうものである。

コンポーネント設計者はコンポーネント分析フェーズで作成された成果物を頼りにこのフェーズを進めることになる。

  • シネマスコープモデルのシナリオ
  • DRO手法を使って作成したオブジェクトレイアウトカード(主にインタフェースカード)
  • DRO手法を使って作成したクラス図やコラボレーション図など
  • 評価用に作成されたプロトタイプ

実際にはコンポーネント設計・実装フェーズで発生する問題からコンポーネント分析をやり直したり、再度洗練させる必要が出てきたりすることもある。よって、コンポーネント分析を再度繰り返すことも必要となるかもしれない。

このような場合は、2つのフェーズをピンポンのように反復して行いながら、パッケージ全体の構造を形成させていくことになる。

クラス構造の詳細化

クラス構造の設計を行い、実装によって検証をおこなう。これを何度か繰り返しながら最終的に適した構造を作り上げる。通常、設計能力が向上するとこの繰り返し回数は少なくなるだろう。

コンポーネントの役割に応じて必要となるすべての公開メソッドを決定する。

コンポーネント分析で作成(実際はDRO手法による)した、インタフェースカードを基に、コンポーネントで公開されるメソッドの仕様を決定する。

コンポーネント構造を具体化する。

コンポーネントを実現するクラスの構造を決定する。その際、コンポーネントの実現のためにいくつかのクラスに役割を分割することもある。このようなクラス分割の動機を以下に示す。

  • 再利用可能な操作部分をクラスにまとめて分離する
    コンポーネントの中からもっと粒度の小さな再利用コンポーネントを見つけた場合、または、その可能性がある場合は、別クラスとして分離する。
  • インタフェースと実装を別クラスにする。
    インタフェースと実装を分離することにより、インタフェースは利用者に公開するクラスとして公開メソッドのみを持つシンプルなクラスとなり、理解しやすくなる。そして、実装クラスは非公開クラスとして利用者から隠せるという利点もある。2つの実現例を図27-1に示す。この2つの方法は、実装を隠すという点で共通しているものである。しかし、両者の特徴を比較すると表27-1のようにそれぞれに長所・短所があり、問題に対する適切な使い分けが必要とされる。

    sorry image only
    図27-1 インタフェースと実装部分を別クラスにする

    表27-1 2つの実装例の比較
    図中の分類 比較項目 特徴
    A.インタフェース継承の利用 解説 インターフェースとなるクラスを継承してクラスに実装部分をおく。
    長所 実装クラスを組み替えやすいため再利用性・拡張性に優れている。
    短所 インタフェースに新たなメソッドが必要とされる場合、実装クラスへの影響度がBよりも高くなることがある。特にインタフェースを継承する実装クラスが多くなると、仕様変更されたインタフェースに答えられない実装クラスをどうするかという問題を抱え込むこともある。
    利用動機 再利用性や拡張性の可能性のある部分に採用する。ただし、インタフェースの仕様があまり変化しないものに適している。たとえば、フレームワークにおける利用者とのインタフェースに利用するなど、拡張の方向性や範囲を明確に定めた上での利用に適している。
    実装方法 Javaではabstractクラスとintafeceによる実現が可能であるが、intafaceを使った方がよい。なぜなら、intafaceを実装するクラスがスーパクラスを持つことができ、自由度が向上するからである。C++では純粋仮想関数で構成されたクラス(abstractクラス)が使われる。
    B.委譲の利用 解説 インタフェースクラスが実装クラスを持ち、インタフェース処理を実装クラスに委譲(delegation)する。
    長所 インタフェースの仕様の変更に柔軟性がある。また、実装クラスをいくつも持ったり、異なるインタフェースと同一の実装クラスを持ったりする(図中の点線部分)ことができる。
    短所 実装クラスとの関係をプログラムする必要があり、インタフェースのメソッドを明示的に実装クラスに委譲しなければならない。
    利用動機 インタフェースの拡張性に柔軟を持たせたい場合。たとえば、サブシステムのような大きな枠組みは仕様変更拡張によりインタフェース仕様が変化することが多い。他のサブシステムに提供するインタフェースをFacadeパターンの概念(第23章にて解説)を取り入れる場合に適している。
    実装方法 メッセージを委譲する実装クラスをインタフェースクラスが集約する。つまり実装クラスのインスタンスをnewして内部属性に保持しておき、メッセージが来たら、そのまま実装インスタンスに処理を伝搬する。
クラスの属性を定める。

コンポーネントの公開メソッドを実現するために必要となる属性を洗い出し、その型を決定する。その際に、属性となるインスタンスの初期化(生成)や終期化(消滅)のタイミングについても検討する。

継承可能とするかを考える。

作成するクラスからサブクラスを作らせることを許可するかどうかを決定する。もし、コンポーネントの継承利用を許可するならば、利用者がサブクラス化によって恩恵を受けるような仕組みを提供し、安全面も保証し、継承して利用するためのドキュメントをコンポーネントリファレンスに含める必要がある。

誤ったクラスの使い方や、中途半端な再利用コンポーネントの開発を避けるために、不用意な継承はしないようにしなければならない。よって、再利用コンポーネントは、継承可能なクラスかどうかをコンポーネントリファレンスに明記していなければならない。

オーバライド可能なメソッドかを明記する。

継承可能なクラスの場合、メソッドの安易なオーバーライドによるトラブルを避けるために、メソッドがオーバーライド可能か否かを、コンポーネントリファレンスに明記する。もちろん、抽象メソッドのようなものはオーバーライドが必須となる。

非公開メソッドを設計する。

公開メソッドを実現するための実装のみを受け持つ非公開メソッドの実現方法を決め、実際にコーディングして動作を確かめる。

コンポーネント利用者の観点で利用パターンを考える。

コンポーネント利用者の観点で、開発するコンポーネントについて考えることで、そのコンポーネントの潜在的な欠点や、間違いやすい利用方法について知ることができる。コンポーネント設計者の知識を一度捨て、「まったくクラスの実装を知らない人が使った場合、どのような間違いが発生するのだろうか」と考えてみるのもとよいことだ。このような観点で、間違いやすい様々なテストケースを想定しながら頭の中で動作のシミュレーションを繰り返し、気が付いた内容についてメモを取る。たとえば以下のようなテストケースを考えるのである。

  • インスタンスを動的に作成した場合の問題点や落とし穴はないか?
  • インスタンスを静的に作成した場合の問題点や落とし穴はないか?
  • インスタンスのコピーが作成された時の問題点や落とし穴はないか?
  • メソッド呼び出しの順番があるものを、呼び出し順を間違った場合はどうなるのか?
  • 運用サイクルの中で、1度しか生成されないよう設計されているインスタンスの消滅・生成を2度以上繰り返してしまった場合にどのような問題が起こるか?また、そのような使われ方に対する防御策はあるか。
  • 運用の中で、1個しか存在してはならないインスタンスを複数生成してしまった場合にどのような問題が起こるか?また、そのような使われ方に対して防御策(Singletonパターンなど)を講ずる必要があるか。
  • 提供するメソッドの戻り値に、オブジェクトの参照を返却している場合、その後の参照オブジェクトの使われ方によって、なんらかの副作用を引き起こしてしまうことがないか?

作成したメモは、コンポーネント仕様の改善に利用される。また、実装レベルで対応できないような問題については、以下のような項目としてコンポーネントリファレンスに記載する。

クラス使用条件 コンポーネント利用にあたっての前提となるような条件
事前条件 メソッドを使用するために必要となる前提条件
メソッド使用条件 メソッド使用における約束事(事前条件には該当しないもの)

27.4 チェックリスト

コンポーネント設計・実装フェーズの作業過程や完了時に、作業内容の評価を行う材料として以下のチェックリストを示す。

  • コンポーネントは、利用者の要求を満たせるか?
    たとえばADGから要求されてコンポーネントを作る場合などに、利用者の要求を実現するためのコンポーネントの利用方法が明確になされなければならない。これはコンポーネントを利用して、どのように要求を実現すべきかについてODGメンバができる限りADGのサポートに入ることができるように、ODG組織としてのサポート体制を定めておかねばならない。
  • コンポーネント利用者に対して、正しい利用法が伝えられているか?
    コンポーネントリファレンスの完成時期は、コンポーネントが提供され使われる時となる。しかしながら実際の開発では、ADGの開発とODGのコンポーネント開発が同時並行的に行われることが多いだろう。
    そのような場合、きちんと完成されたドキュメントを出そうとする労力よりもコンポーネントを完成させることを最優先させた方が、全体的な進捗が進みやすいこともある。 そのようなケースでは、ADGメンバとODGメンバの柔軟な対応が望まれる。たとえば、口頭で説明できる程度のコンポーネントの使い方であれば、ODGメンバに使い方を教えてもらえばよい。また、もっと複雑なコンポーネントでは、コンポーネントリファレンスの原型となるドキュメントをADGに提供しなければならない。たとえば、DROで作成したオブジェクトレイアウトカードやサンプルソースなどを使って、ADGに提供されるコンポーネントのインタフェース部分を明確に伝えるよう努力をしなければならない。

reference:

参考文献:

  • デザインパターン/Erich Gamma他著/本位田真一、吉田和樹/ソフトバンク
    GoFとは著者の4人組(Gang of Four)ということでGoFデザインパターンと呼ばれている。

*begin*back*foward*end*contents

この記事のトップへ