オブジェクト指向設計では,適切なクラスに適切な役割(責務)を割り当てることが肝心である。設計作業中に遭遇するさまざまな選択肢から,対象となるシステムに応じて最適な判断を下す必要がある。ここでは,判断のよりどころとして有効な手法である「GRASPパターン」を紹介する。

 読者の中には,実際に日々の業務の中で,オブジェクト指向設計に携わっているITエンジニアも多いことだろう。そういう人たちへ質問がある。明確な方針を持って設計を行っているだろうか。「言われてみれば,あまり意識したことはないな」という人が,案外多いのではないだろうか。

 オブジェクト指向設計とは,システムに対する様々な条件や制約を考慮し,オブジェクトの最適な役割と,複数のオブジェクトの役割について協調関係を構築していく作業である。役割とは,「オブジェクトが果たすべき機能」のことで,オブジェクト指向では「責務(Responsibility)」と呼ぶ。通常はクラスにメソッドを実装することで,責務を実現する。

 オブジェクトに最適な役割を割り当てることは,「適切なクラスに適切な責務を配置する」ことに他ならない。明確な方針を持たないまま設計を行うと,様々なクラスとメソッドの関係に整合性がなくなり,複雑なシステムができあがる可能性が高い。システムの規模が小さい場合はまだしも,規模が大きくなると破綻することは明らかだ。

責務配置の基本原則

 それでは,どのような方針に基づいて責務を配置すればよいのだろうか。そこでよりどころとなるのが,「GRASP(General Responsibility Assignment Software Patterns)パターン注1)」である。


表1 GRASPパターンの概要
[画像のクリックで拡大表示]

図1 結合度が高い設計と低い設計の違い
[画像のクリックで拡大表示]

図2 凝集度が異なるクラスの例
[画像のクリックで拡大表示]

 GRASPパターンとは,Craig Larman氏がその著書注2)の中で示した9つのパターンを指す(表1[拡大表示])。“パターン”とは言うものの,第4部で紹介した「GoFのデザインパターン」のような設計テクニックを示すものではない。オブジェクトに責務を割り当てる際の基本原則,方針を整理してまとめたものである。筆者は新人にオブジェクト指向設計を教える場合,GRASPパターンを必ず理解するよう奨めている。各パターンの詳細な内容については前出の文献を参照していただきたい。

 各パターンが示す原則は,どれも非常にシンプルなものである。中級者以上であれば,日々の作業の中で意識せずに自然に使用しているものがほとんどのはずだ。例えば「MVCアーキテクチャ」はGRASPパターンの中のControllerパターンを適用したものだし,GoFのデザインパターンのほとんどは,Pure FabricationパターンやIndirectionパターンに基づいている。

鍵は結合度と凝集度

 GRASPパターンの基本となる概念を,まず理解していただきたい。それは,「結合度(coupling)」と「凝集度(cohesion)」だ。これらはもともと構造化設計で提唱された概念である。その考え方をオブジェクト指向設計に適用したものと考えてよい。

 結合度とはオブジェクト間の「関連の度合い」を示すものだ。関連とは,オブジェクト同士の「意味的・物理的なつながり」を示す。例えば「商品」オブジェクトと「顧客」オブジェクトには,「注文する」という関連が成り立つ。他のオブジェクトとの関連の数が多く,関連の仕方が強い場合,結合度は高くなる。

 結合度が高いシステムでは,特定のオブジェクトに変更を加えると,システム内の他の広い部分に影響を与えてしまう。このため,後から開発に携わったSEや,保守担当のエンジニアが理解しにくく,変更が困難なものとなり,保守性も低下する(図1[拡大表示])。

 一方の凝集度とは,オブジェクトが持つ機能の「意味的なまとまりの度合い」を示すものである。お互いに関係のない多数の機能が無秩序にちりばめられているオブジェクトは,凝集度が低いということになる。それらは理解しにくく再利用が難しい。逆に凝集度が高いオブジェクトは機能の関連性が強く,オブジェクト自体が持つ役割や意図が明確であり,直感的に理解しやすい。

 例えば図2[拡大表示]左は,凝集度が低い設計の例である。顧客情報の登録,商品情報の登録,データベース・アクセスといった,関係のない機能が混在している。

 凝集度を高めるには,クラス内の関連性が強いメソッドをひとまとめにして別々のクラスとして抽出し,それらを関連付ければよい(図2右)。これは,いわゆるリファクタリング注3)の「クラスの抽出」と呼ばれるテクニックである。

 再利用や拡張,保守をしやすいオブジェクト指向システムを設計するためには,何よりも「オブジェクト間の結合度を最小化し,オブジェクトの凝集度を最大化する」ことが重要だ。GRASPパターンでは,これを「Low Coupling(疎結合性)パターン」および「High Cohesion(高凝集性)パターン」として明示している。

 これら2つのパターンは,GRASPパターン全体を根底で支える考え方でもある。例えば「Controller」,「Pure Fabrication」,「Indirection」の各パターンは,オブジェクト同士を仲介するオブジェクトを導入し,問題領域のオブジェクトとそれ以外のオブジェクトを分離する。これにより,結合度を小さくし,また凝集度を高く維持しようとするものだ。


渡辺 康隆(わたなべ やすたか)/デュオシステムズ ビジネスソリューション・グループ システムアーキテクト
広島大学工学部卒業後,メーカー系研究開発部門を経て,デュオシステムズに入社。現在,システムアーキテクトとしてオブジェクト指向技術を活用したシステム開発に従事。著書に「分散オブジェクトモデリングガイド(ピアソン・エデュケーション)」,訳書に「J2EEクイックリファレンス(O'REILLY)」など

次回に続く