今更の投稿でごめんなさい・・・。
とあるお客様向けにグリッドの共通モジュールを開発するにあたり、
デザインパターンの重要性を改めて感じました。
そこで今回は、参考にした書籍デザインパターンとともに学ぶオブジェクト指向のこころの中から、
「1章 オブジェクト指向パラダイム」をまとめます。
オブジェクト指向とはどういう考え方なのか、それまでの構造化プログラミングと比較しながら考えていきます。
忘年会の幹事業を例に考えてみる
今日は会社の忘年会!
幹事のあなたは、出席者を誘導しなければなりません。
しかも、各部署で会場が異なります。
構造化プログラミング的アプローチ
構造化プログラミング的アプローチで考えてみると、どのようになるでしょうか?
- 手順 -
- 忘年会出席者のリストを取得する。
- 取得した各出席者に対して、以下の対応をする。
( 1 )その出席者の部署を調べる
( 2 )その部署の会場を調べる
( 3 )その会場までの行き方を調べる
( 4 )その出席者に伝える
- 手順を実行するための手続き群 -
- 忘年会出席者のリストを取得する機能
- 出席者の情報(部署・会場・行き方)を取得する機能
- 出席者へ忘年会会場への行き方を教えるプログラム
- 1〜3を手順通りに実行する制御プログラム
このように、「社員を忘年会会場へ誘導する」という問題を、小さな要素に分解していきます(機能分解)。
ですが、実際にはこんなことしませんよね・・・。
「各部署の会場と行き方を出席者に連絡して、後は各自で来てください」で良いはずです。
各社員はもちろん自分の所属する部署を知っていますので、自分で会場と行き方を確認すれば良いのです。
構造化プログラミング的アプローチの欠点
それでは、構造化プログラミング的アプローチのどこが問題なのでしょうか?
制御プログラムに責任が集中し、変化に対応しづらい
機能分解した訳ですから、この分解した機能を正しい順序で呼び出す制御プログラムが必要になります。
この制御プログラムは、全ての機能を正しく制御するという大きな責任を課せられることとなります。
それでは、
「新入社員は買い出しをしてから会場に向かって!」となったらどうなるでしょうか?
出席者が新入社員かどうか確認する機能を追加して、
新入社員の場合は、買い出しに行ってから会場に行くように制御プログラムを変更して・・・
と、変更の影響範囲が広く、コードが複雑化しやすくなってしまいます。
ユーザ自身によって、もしくは技術の発展など環境の変化によって、要求は常に変化していきます。
この要求の変更による影響を少なくし、より柔軟に対応できるようにと生み出されたのが、オブジェクト指向です。
オブジェクト指向的アプローチ
構造化プログラミング的アプローチでは、機能に注目して問題を分解していきましたが、
オブジェクト指向的アプローチでは責任に注目して問題を分解していきます。
「各部署の会場と行き方を出席者に連絡して、後は各自で来てください」
先程のこの考え方が、オブジェクト指向的アプローチになります。
幹事は会場に来てくださいと指示をするだけで、どのようにして会場に行くかは各社員に委ねられています。
この幹事や社員がオブジェクトにあたり、それぞれ以下のような責任を持っています。
- 幹事
会場へ向かうよう、社員に告げる - 社員
所属する部署を知っている
会場を知っている
会場へ向かう
つまり、オブジェクトはある物事に対して責任を持つものになります。
機能ではなく、責任に注目して分解することで、
なぜ要求の変化により柔軟に対応できるようになるのでしょうか?
オブジェクトを考える際の3つの観点
オブジェクトを考える際には、どのような観点で見ているかが重要になります。
-
概念レベル:何に対して責任があるのか
このレベルにおいてオブジェクトは、責任の集合となる -
仕様レベル:どのように使用されるのか
このレベルにおいてオブジェクトは、振る舞い(メソッド)の集合となる -
実装レベル:自身の責任をどう全うするのか
このレベルにおいてオブジェクトは、データと処理となる
この考え方により、
幹事は「社員が実際にどのように会場へ向かうのか」といった詳細(実装レベル)を知る必要はなく、
「会場へ向かう」という公開されたメソッド(仕様レベル)を持つ社員に対して、
「会場へ向かうよう指示をする(=社員オブジェクトのメソッドを呼び出す)」(概念レベル)だけで良くなります。
凝集度と結合度
-
凝集度
モジュール内の処理の関連性
高いほど、理解がしやすいコードなる -
結合度
モジュール同士の関連性
低いほど、要求の変更による影響を受けない
このように、高い凝集度、低い結合度のモジュールが求められます。
機能に注目して分解すると、高い凝集度にはなりますが、結合度が高く、ある機能への変更が、制御プログラムやその他の機能に思わぬ影響を与えてしまう可能性が高くなってしまいます。
責任に注目して分解することで、まず、大きい責任を持った制御プログラムは必要なくなります。
さらに、モジュールの呼び出し側は、呼び出したモジュールの実装の詳細を知る必要はないため、結合度は低くなります。
まとめ
オブジェクト指向では、問題を責任に注目してオブジェクトに分解していきます。
そして、このオブジェクトには、概念・仕様・実装の3つの観点があり、概念レベルでオブジェクト同士がコミュニケーションをとることで、要求の変化による影響を最小化しています。
この章では、「オブジェクトはクラスという設計書に基づいて作られた実体である」というような、実装レベルだけの話ではなく、仕様レベル、概念レベルで捉えることの重要性が説明され、私自身実装レベルから考えていたなと感じました。
この書籍内では理論に重点を置いてデザインパターンが説明されていますので、
社内研修で取り入れることも視野に入れて、引き続き読み進めていきたいと思います!