sait0sのブログ

技術で広く浅く遊んでいる、エンジニアの真似事をしている学生です

「オブジェクト指向のこころ」を読んだ

今年の夏インターンで、アーキテクトやモデラーとして活躍するつよつよエンジニアを見て、何となくアーキテクトに憧れを抱くことがありました。そんな中で、「アーキテクチャやソフトウェア設計を理解するなら、オブジェクト指向デザインパターンは理解しておいたほうが良いよね!」とふと思ったわけです。

 

実は、デザインパターンJavaを始めて1年目くらいの大学1年のときに、かの有名な「Java言語で学ぶデザインパターン入門」を買ったものの、難しすぎて本棚に隠していました。(あと、カツオのたたきは食べたことない)

 

そんな中で、本屋をぶらついていたら、面白そうな本があったので衝動買いしました。

あと、今まで Javaばっかり触っていたので、「いくつか知ってるやつもあるし、余裕だろ」という甘い覚悟で臨みましたね。

対象読者

本書のサンプルコードは Javaで書かれていますが、専用サイトに C++C#での実装が記載されています。基本的に、オブジェクト指向の三大要素がわかっていれば、問題ないです。

 

読む際の注意点として、Java言語の interfaceとソフトウェアにおけるインターフェースを混同すると、何を言っているのかわからなくなります。本書に記載されている "インターフェース" は後者です。あと、ほとんど abstractクラスで実装されていますが、interfaceで実装できるのであれば、interfaceを使うのが一般的だと思います。

あらすじというか概要

第1部 (1~2章)

1章では、オブジェクト指向の三大要素や凝集度、結合度の概念について説明しています。エンジニアなら知っていて当然みたいな雰囲気はありますが、本質をしっかりと理解している人は少ないのではないでしょうか。自分はそうでした。

読んでいるときは「当たり前だよね!」と思っても、本書を読み終わった後でもう一度見ると、違った観点で理解が深まると思います。オブジェクト指向設計では、流動的要素を概念レベル、仕様レベル、実装レベルで抽出し、コードを実装していきます。これらをいかにオブジェクト指向を用いて影響範囲を抑えるかが重要です。この辺の概念は、次章以降でも何度も提唱されています。

 

2章は、UML(統一モデリング言語)の説明になります。次章以降からUMLを用いて解説されているので、UMLの読み方を学びます。すごく簡単なので覚えることは少ないですが、モデリングした設計が可視化されるので理解しやすくなります。

昔は、UMLが新たな言語として流行するみたいな雰囲気もあったようですが、今は全く使われていないですよね。

第2部 (3~4章)

3~4章では、この本でサンプルとして用いる CAD/CAMシステムの概要とそれを用いた実装例について説明しています。設計に携わった経験がある方なら、設計時の問題点をイメージしやすいのかなと思います。それをオブジェクト指向で解決するにはどうすれば良いか?ということを考えるパートです。

 

CAD/CAMシステムなんて、今は知らない人も多いのではないでしょうか。自分はコナンで初めて知りました。

第3部 (5~11章)

この章から、GoFデザインパターンに入っていきます。

最初に、"Facadeパターン" と "Adapterパターン" を見ていきます。クライアント側からシステムの実装や内部設計を意識させないために、カプセル化のみを用いた比較的簡単な解決方法です。この2つのパターンは、他のデザインパターンと同時に利用されることもあるので、かなり重要なパターンだと思います。

 

次に、"Strategyパターン" と "Bridgeパターン" になります。ここから interfaceや抽象クラスを用いるため、複雑になります。クライアント側から見た Aシステム、 Aシステムから見た Bシステムといった2つの観点からそれぞれ見ていく必要があります。どのようにオブジェクトに責任を持たせていくかといった考え方を持つ必要があるため、本当に難しいです。

 

最後が、"Abstract Factoryパターン" です。ファクトリの概念自体は DDDにも出てきますが、ほとんど同義なのかなと思います。各ファミリに対して、ファクトリが実装を提供するというイメージですね。まずファクトリを用意し、クライアントはファクトリを利用するが実装は関知しない、ファクトリ(もしくはConfig)が実装を決定するといった考え方が根底にあります。あと、Abstract Factory単体で何かを解決するということはないのかなと思います。後述にもある通り、生成に関するデザインパターンと一緒に用いることが多いと思います。

第4部 (12~13章)

ここでは、パターンの適用方法を見ていきます。概念レベルから問題点を抽出し、複雑にしていく必要があるということを述べています。その後に、CAD/CAMシステムからデザインパターンを組み合わせた解決方法について考えます。一番重要なことは、デザインパターンはシステムの問題点を解決するために提案された手段であるということです。そのため、デザインパターンの組み合わせは、各デザインパターンの問題点へのアプローチであるということを理解して、システムに適用する必要があると書かれています。

第5部 (14~16章)

モデリング手法や設計アプローチについての説明です。どのように分析し、モデリングをして、デザインパターンを適用して設計するかということが述べられています。SOLID原則を意識することやパターンへの過度な信頼は禁物であるということも書かれています。オブジェクト指向設計の際のアンチパターンについても語られているので、重要です。

第6部 (17~19章)

"Decoraterパターン" 、"Observerパターン" 、"Template Methodパターン" を見ていきます。ここでは、流動的要素をどのように保持していくかということに焦点を当てたものです。簡単に言うと、オブジェクト指向によるイベント管理方法になります。Java をやっている方なら、○○IventListenerとか○○Templateとか馴染みがあるのかなと思います。多くのJava ライブラリにも利用されているデザインパターンです。

第7部 (20~24章)

"Singleton / Double-Checked Lookingパターン" 、"Object Poolパターン" 、"Factory Methodパターン" を見ていきます。今までとは少し観点が違って、生成に関するデザインパターンになります。ファクトリからどのように実装を提供するかの違いになります。ここら辺は、馴染みのある人も多いのかなと思います。

第8部 (25~26章)

今までのまとめ!!

 

読んでみて

すごくわかりやすかったです。「Java言語で学ぶデザインパターン入門」がコードで理解するなら、こちらは理論で理解するという感じですね。

それでも、他の記事や実装例も参考にしましたし、実際にデザインパターンでの設計を見たことがないので、理解度7割って感じですが、、、(それと、内容が濃いため、全体は360ページ程度ですが読み終わるまでに300hはかかりました)

 

何となく気づいた人もいると思うのですが、23個全てのデザインパターンは取り扱ってないです。主要かつ重要なパターンに絞ったのかなと思います。

 

何度も書かれていますが、"オブジェクトへの責務" 、"オブジェクトの集約" 、"カプセル化" の重要性を説いています。

  • 継承よりも集約を用いること
  • カプセル化の本質は、(メンバーやメソッドだけでなく)型やオブジェクトの隠蔽
  • オブジェクトへの責務を明確にすること

これらを理解するのに、かなり時間がかかりました。現代のソフトウェア開発も同じですが、開発における不確実性要素に対して、いかに柔軟に対応することができるかということが根底にあります。これらを上手く使って、不確実性要素に対して最小限の変更に抑え、新規機能の追加では変更を加えないという SOLID原則に則った設計にすることが求められます。(注意点あり -後述- )

 

あとは、凝集度や結合度についても少し間違った理解をしていたのだと痛感しました。

単に、高凝集は関連するメソッド群でまとめたもので、疎結合は機能や役割ごとに分割させるという認識でした。流動性要素の集約やオブジェクトへの責務という観点からみると、持つべきでないモジュールやクラスに責務が与えられていたり、 if文や switch文で無理やり書いていたなと反省しました。(switch はパターンを適用するフラグと書かれているところが良かった)

 

そうは言うものの、責務を明確化することや集約することには限界はあると思う。設計時に分析して不確実性要素を洗い出すわけですが、あらゆることを想定したら分析地獄に陥るし、下手をすればクラス爆発を起こして逆に保守しにくくなってしまう。ここら辺は、システム要件やアーキテクトの腕次第なのかなと思います。ただ、何よりも難しいのは、複雑なシステムに対応するためにデザインパターンを複数用いて対処するということかもしれないです。単一のデザインパターンで解決できることの方が少なく、何かしらのパターンを組み合わせて対応することがほとんどであるということ。間違った組み合わせを選択すると、その先も地獄になってしまう。ここが本当に難しい、、、

 

最後に、DDD やアーキテクチャアジャイル開発にもつながる部分はたくさんあるのかなと思いました。ここら辺の知識が浅いので、今のところ何とも言えないが、こちらの知識もつけていきたいです。(単純に理解不足)

 

学生にオブジェクト指向は早すぎたかもしれないとは思いつつも、アーキテクトって何か響きがかっこいいですよね。それは別として、以前からこの分野には興味あったので、さらに追及してみたいですね。

 

(注意)

SOLID原則には触れているものの、ジレンマというか、トリレンマ(?)のように、これら全てのソフトウェア原則をカバーすることは絶対にできないと思っている。どれかを諦めなければならなず、絶対的なものではないというのは注意しなければならない。ここら辺は、メリット・デメリットと一緒に触れてほしかったです。