GRASP (General Responsibility Assignment Software Patterns、またはPrinciples)は、 「オブジェクト設計と責任割り当てにおける9つの基本原則」 [ 1 ]: 6のセットであり、クレイグ・ラーマンが1997年の著書『Applying UML and Patterns 』で初めて発表しました。
GRASPで使用されるさまざまなパターンと原則は、コントローラ、クリエーター、間接参照、情報エキスパート、低結合、高凝集、ポリモーフィズム、保護されたバリエーション、および純粋なファブリケーションです。[ 2 ]これらのパターンはすべて、多くのソフトウェア開発プロジェクトに共通するソフトウェアの問題を解決します。これらの技術は、新しい作業方法を作成するために発明されたのではなく、オブジェクト指向設計における古くからある実績のあるプログラミング原則をより良く文書化および標準化するために発明されました。
ラーマンは、「ソフトウェア開発における重要な設計ツールは、設計原則について十分に教育された頭脳である。UMLやその他の技術ではない」と述べている。[ 3 ]: 272したがって、GRASP原則は実際には精神的なツールセットであり、オブジェクト指向ソフトウェアの設計を支援する学習補助ツールである。
オブジェクト指向設計において、パターンとは、新たな状況にも適用可能な問題と解決策を記述した名称付きのコードです。理想的には、パターンは様々な状況下でその解決策をどのように適用すべきかを示し、その際の制約やトレードオフを考慮します。多くのパターンは、特定の問題カテゴリに対して、オブジェクトへの責任の割り当てを導きます。
問題:オブジェクトに責任を割り当てるための基本的な原則は何ですか? 解決策:責任を果たすために必要な情報を持っているクラスに責任を割り当てます。
情報エキスパート(エキスパートまたはエキスパート原則とも呼ばれる)とは、メソッド、計算フィールドなどの責任をどこに委任するかを決定するために使用される原則です。
情報エキスパートの原則を用いると、責任を割り当てる一般的なアプローチは、与えられた責任を検討し、その責任を果たすために必要な情報を特定し、次にその情報がどこに保存されているかを特定することである。
これにより、その責任を果たすために必要な情報を最も多く持っているクラスに責任が課されることになる。[ 3 ]: 17:11
関連するパターンまたは原則:低結合、高凝集
オブジェクトの生成は、オブジェクト指向システムにおいて最も一般的な活動の一つです。どのクラスがオブジェクトを生成する責任を負うかは、特定のクラスに属するオブジェクト間の関係における基本的な特性です。
問題:オブジェクトは誰が作成するのかA? 解決策:一般的に、以下のいずれか、またはできれば複数に該当する場合は、Bオブジェクトを作成する責任をクラスに割り当てます。A
Bインスタンスを含むか、または複合的に集約します。ABレコードのインスタンスのインスタンスAB密接に使用するインスタンスのインスタンスAB、 のインスタンスの初期化情報を持っておりA、作成時にそれを渡します。[ 3 ] : 16:16.7関連するパターンまたは原理:低結合、工場パターン
コントローラパターンでは、システムイベントの処理責任を、システム全体またはユースケースシナリオを表す非UIクラスに割り当てます。コントローラオブジェクトは、システムイベントの受信または処理を担当する非ユーザーインターフェースオブジェクトです。
問題:入力システムイベントの処理は誰が担当すべきか? 解決策:ユースケースコントローラは、ユースケースのすべてのシステムイベントを処理するために使用すべきであり、複数のユースケースに使用できます。たとえば、 「ユーザーの作成」と「ユーザーの削除」というユースケースの場合、 2つの別々のユースケースコントローラではなく、UserControllerという単一のクラスを使用できます。あるいは、ファサードコントローラを使用することもできます。これは、イベント処理を担当するオブジェクトがシステム全体またはルートオブジェクトを表す場合に適用されます。
コントローラは、UI レイヤーの先にある最初のオブジェクトとして定義され、システム操作を受け取り、調整(「制御」)します。コントローラは、実行する必要のある作業を他のオブジェクトに委任し、アクティビティを調整または制御します。コントローラ自身は多くの作業を行うべきではありません。GRASP コントローラは、情報システムの論理アーキテクチャにおける共通レイヤーを持つオブジェクト指向システムのアプリケーション/サービスレイヤー[ 4 ]の一部であると考えることができます(アプリケーションがアプリケーション/サービスレイヤーとドメインレイヤーを明示的に区別していると仮定した場合)。
間接参照パターンは、中間オブジェクトに2つの要素間の仲介責任を割り当てることで、結合度を低く抑え、2つの要素間の潜在的な可能性を再利用します。その一例として、モデル・ビュー・コントローラパターンにおいて、データ(モデル)とその表現(ビュー)間の仲介を行うコントローラコンポーネントを導入することが挙げられます。これにより、両者間の結合度を低く保つことができます。
問題:2つ(またはそれ以上)の要素間の直接的な結合を避けるために、どこに責任を割り当てるべきか?結合度を低く保ち、再利用の可能性を高めるために、オブジェクトをどのように分離すべきか?
解決策:他のコンポーネントやサービスが直接結合しないように、中間オブジェクトにそれらの間の仲介役を割り当てます。 中間オブジェクトは、他のコンポーネント間に間接的な接続経路を作り出します。
結合度とは、ある要素が他の要素とどの程度強く結びついているか、他の要素に関する情報を持っているか、あるいは他の要素に依存しているかを示す指標です。結合度が低い場合、以下のメリットに対する責任の割り当て方を決定する評価パターンとなります。
高凝集度とは、オブジェクトを適切に焦点化し、管理しやすく、理解しやすくするための評価パターンです。高凝集度は一般的に低結合度をサポートするために用いられます。高凝集度とは、特定の要素群の責任が密接に関連し、特定のトピックに高度に焦点を絞っている状態を指します。プログラムを正しくクラスやサブシステムに分割することは、名前付きクラスやサブシステムの凝集性を高める活動の一例です。一方、低凝集度とは、例えばサブシステムなどの要素群が、関連性のない責任を多数抱えている状態を指します。構成要素間の凝集度が低いサブシステムは、全体として理解、再利用、保守、変更が困難になる傾向があります。[ 3 ]: 314-315
ポリモーフィズムの原則によれば、型に基づく振る舞いのバリエーションを定義する責任は、そのバリエーションが発生する型に割り当てられます。これはポリモーフィック操作を用いて実現されます。型の利用者は、型に基づく明示的な分岐ではなく、ポリモーフィック操作を用いるべきです。
問題:型に基づく代替案をどのように扱うか?プラグイン可能なソフトウェアコンポーネントをどのように作成するか? 解決策:関連する代替案や動作が型(クラス)によって異なる場合、ポリモーフィズム操作を用いて、動作が異なる型にその動作の責任を割り当てる。(ポリモーフィズムにはいくつかの関連する意味がある。この文脈では、「異なるオブジェクトのサービスに同じ名前を付けること」を意味する。)
保護されたバリエーションパターンは、不安定性の中心をインターフェースでラップし、ポリモーフィズムを使用してこのインターフェースのさまざまな実装を作成することにより、要素を他の要素(オブジェクト、システム、サブシステム)のバリエーションから保護します。
問題:オブジェクト、サブシステム、およびシステムを設計する際に、これらの要素における変動や不安定性が他の要素に望ましくない影響を与えないようにするにはどうすればよいか? 解決策:変動や不安定性が予測される箇所を特定し、それらの周囲に安定したインターフェースを作成する責任を割り当てる。
純粋なファブリケーションとは、問題領域の概念を表さないクラスのことで、結合度を低くし、凝集度を高め、再利用性を向上させるために特別に作られたものです(情報エキスパートパターンによって提示されたソリューションでは実現できない場合)。このようなクラスは、ドメイン駆動設計では「サービス」と呼ばれます。
関連するパターンと原則 • 低結合度。 • 高凝集度。