MENU
現役エンジニアがIT周りを解説しています!

【オブジェクト指向設計】GRASPの9つのパターンを分かりやすく解説

GRASP。。。
それはオブジェクト指向設計に用いる、9つのパターンセットである。。。

目次

GRASPとは

General
 汎用
Responsibility
 責任
Assignment
 割り当て
Software
 ソフトウェア
Patterns
 パターン
(or Principle  原則)

の頭文字を並べた言葉です。

オブジェクト指向設計に向けた、9つのパターンを指します。

これらは1997年に出版された、「Applying UML and Patterns(実践UMLパターン)」で初めて紹介されました。

著:クレーグ ラーマン, 原名:Larman,Craig, 翻訳:光江, 依田, 翻訳:智夫, 依田, 翻訳:睦, 今野

余談ですが、grasping(理解)ともかけているとうわさされています🤔

9つのパターン

GRASPのパターンは、以下の9つに分類されます。

  • 情報エキスパート
  • 高凝集
  • 疎結合
  • 生成者
  • コントローラ
  • 間接化
  • 多様性
  • 保護的変容
  • 純粋造形

名前でだいたい分かるものもありますが、1つ1つ解説をしてきます!

それぞれ、オブジェクト指向設計における疑問に答える形で説明されています。

情報エキスパート

オブジェクトへの責任割り当てにおける、一般原則は何か?

責務を実行するのに必要な情報を持っているクラスに責任を割り当てる。

処理を実行するのは、必要な情報をすべて持ったクラスにその処理責務を割り当てます。

情報エキスパートに必要な情報が集まってくるので、ほかのクラスとの結合度合が小さくなります。

このパターンを適切に使いこなした設計を行うと、システムの理解がしやすくなります。

また、維持や拡張もしやすくなり、将来の再利用性も高まります。

情報エキスパートは、オブジェクトの責務を考える際の一般的な原則です。

高凝集

複雑さを回避するには、どう設計すべきか?

1つの責務を全うするようなクラスに対して、必要最低限のプロパティとメソッドを持たせる。

名前の通り、凝集度を高くしようよ、という原則です。

ある処理について、その処理を行うのに必要なクラスはそれだけを行い、ひとまとまりとして考えやすくします。

凝集度が低いと、あちらこちらに必要なものが散らばっているので、変更や再利用が難しくなります。

凝集度が高い=いい設計ということがよく問われます!

設計の5原則の「単一責任の原則」は凝集度を高めるための原則です。

疎結合

再利用性を高めるには、どう設計すべきか?

クラス間の関連性と依存性を可能な限り小さく設計すべきである。

各クラスの公開メンバを少なくし、クラス間の関連性・依存性を出来るだけ持たせないようにするという原則です。

具体的には、publicな情報は、特定のインターフェースに情報を集約させるように設計します。

ただしこれはとても難しく、他の原則と相反する実装になる場合もあるので、「念頭に置きつつ吟味する」ことが必要です。

結合性が低い(疎結合性が高い)=いい設計ということがよく問われます!

凝集度と一緒に覚えてください。

基本的に
凝集性が高いと、結合性は低くなります!
結合性が高いと、凝集性は低くなります!

設計の5原則の「オープンクローズドの原則」や「依依存関係逆転の原則」は疎結合性を高めるための原則ともいえます。

生成者

インスタンスを生成する責任は、だれが持つべきか?
  • コンポジション先
  • アリゲーション先
  • 生成を記録するもの
  • 密接に使用するもの
  • 生成に必要な情報を持つもの
    (など)

この原則に従うと、

  • 疎結合性が高くなる
  • カプセル化がしやすくなる
  • 再利用性が高まる
  • 理解しやすくなる

などのメリットが生まれてきます。

特にGoFのデザインパターンの1つである、Factoryパターンが該当します。

コントローラ

システムの入力、イベントを扱うのはだれがいいか?

該当システムを扱うコントローラクラスがよい。そして、その責務をすべて扱うべき。

これは、システム、イベントからの入力は1つのクラスで扱えるコントローラクラスを作ろうね、というお話です。

例えば、マウスの右クリックイベントと、左クリックイベントを別のクラスが扱っていたら分かりづらいですよね。。

そういった処理はすべて同じクラスに持たせて、書く側にも分かりやすいようにしようね!っていう感じです。

GUI開発でよくある話

画面のUIクラスに、何かしら計算処理などを割り当ててはだめだよ、という経験則です。

イベントに対しては、UIクラスからコントローラクラス/メソッドを呼び出し、処理を委譲するように設計します。

こうすることで、画面の変更、たとえばボタンの変更や処理の追加などに対応しやすくなります。

間接化

オブジェクト同士の蜜結合を回避し、疎結合性を高めた設計ができるか?

オブジェクト同士が直接関係を持たないように、仲介するための中間クラスを作成して、そのクラスに責務を割り当てる。

これも名前の通り、直接的な関係を避け、間接的なつながりとする設計です。

これによって、元の2つのクラス間の疎結合性が高まり、再利用性が高まります。

ただし、その分クラス数は増えてしまうので注意です。

多様性

どのように多様性を確保するクラスを設計すべきか?

同じメソッド名で設計をして、オブジェクトの異なる動作の受け皿となる型を作成する。

分かりにくいですが、ポリモーフィズムというやつです👌

普段たくさん使用していると思うので詳細は省きますが、コーディングもしやすくなるし、扱いやすくていいですよね!

保護的変容

変更が生じると決まっているクラスに対し、そのクラスが実際に変更されたときの影響範囲を狭くするにはどう設計したらよいか?

変更する可能性のある個所を明確にし、その箇所が変更されても、変更しなくて使えるインターフェースクラスを作成しておく。

これは考えたら分かりそうなことを明文化しています。

例えば「設定で切り替わる値」などは設定クラスなどに持たせて、そこから引き出すようにしますよね。

ちゃんと吟味して設計しようね、ということ忘れないようにする原則ですね。

純粋造形

専門オブジェクトをサポートするが、そこから離れた純粋な機能オブジェクトは存在するか?

オブジェクトに対して、自由に分離結合でき、これらを操作するインターフェースがこれにあたる。

ちょっと何言っているかわからないですね(笑)

情報エキスパートを用いようとしてもなんかうまくいかない、そんなときに使います。

対象の概念を表すクラスではなく、クラスを増やして再利用可能性を実現するように設計します。

この種類のクラスはドメイン駆動設計ではサービスと呼ばれるものなので、ドメイン駆動設計を勉強してみると「ああこういうことか」となるので、ぜひこちらも勉強してみてください!

まとめ

9つもパターンがあり、何個か非常に理解しにくいものだったかと思います。

これらは、「こういうものもあるんだ」と念頭に置き、実際の設計を見ていく中で、「ああ、こういう意味か!」と実感していくものだと思います。

しっかり頭の片隅に置きつつ、課題に取り組んでみてください!

今回も最後までお読みいただきありがとうございます🙇‍♂️

わからないことがあれば、twitterにて質疑応答し、記事に反映させていただきます!

お気軽にお問い合わせください!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
目次