たばりばりスタイル

たばりばりスタイル

バリバリバリ⚡︎

「オブジェクト指向設計実践ガイド」を読んだ

開発者に転向してもうすぐ 1 年になります。
これまでは雰囲気で開発していたので、Web 業界で一般的である開発手法や考え方などを学びたくなりました。
例えば、クリーンアーキテクチャドメイン駆動開発などが当てはまるのですが、これらを学ぶにもまずはベースにオブジェクト指向の知識が必要となると思っており、まずはその初歩として、「オブジェクト指向設計実践ガイド」通称 POODR 本を読むことにしました。

実は同じようなことを半年前に考え、1 度読み終わっているのですが、駆け出したばかりの開発者には時期尚早で、読んでいて身につかない感覚がありました...。
なので今回は、満を持して読んだ感じです。

感想

オブジェクト指向設計における考え方やアンチパターンリファクタリングの仕方が丁寧に書かれていて、すごくためになりました。特に継承やコンポジションの違いや、テストの観点など、実務ですぐに使えそうな知識がありがたかったです。
ただ、この一冊だけで満足できるか?と言われると、物足りない感じはありました。例えば、この本で "オブジェクト指向設計者の道具" として原則とデザインパターンを紹介しますが、デザインパターンについてはほとんど触れていないので、他の書籍に埋める必要があると感じました。
また、筆者にすべて納得!というような訳でもなく、静的型付けと動的型付けの比較における考えで、型とメソッドの定義は省く方が楽的なニュアンスについては少し違和感を感じる部分もありました。
ただ、トータルすると読んでかなり良かったと思っていますし、実務に取り入れたい考えばかりでした。

読書中に残しているメモがあるので、雑に抽出した自分用まとめを貼っておきます。

※ 解釈にズレがある場合がありますのでご注意ください。

雑なまとめ

第1章 オブジェクト指向設計

オブジェクト指向設計の考えたや原則やパターンについて触れている章。

詳細設計における筆者の考え方が印象に残った。

雑なメモは下記。

第2章 単一責任のクラスを設計する

単一責任がもたらす恩恵を色々教えてくれる章。

雑なメモは下記。

  • シンプルであれ。そして、いま求められる動作を行い、かつあとにも変更が楽なように設計しろ
  • TRUE なコードは、将来のニーズを満たす変更を加えることができる
    • (T) Transparent : 見通しが良い
    • (R) Reasonable : 合理的
    • (U) Usable : 利用性が高い
    • (E) Exemplary : 模範的
  • クラスが何をしているか定める方法は、1 文でクラスを説明してみること
    • "それと" が含まれれば、そのクラスは 2 つ以上責任持ち
    • "または" が含まれれば、クラスの責任は 2 つ以上あり、互いにあまり関連しない責任を負っている
  • メンテナンス性の高いオブジェクト指向ソフトウェアへの道のりは、単一責任のクラスから

第3章 依存関係を管理する

依存についての考え方や DI について書かれている章。

動的型付け言語と静的型付け言語について比較する部分もある。

雑なメモは下記。

  • クラスが他クラスを知るほど、あたかも一つのエンティティのように振る舞う
  • 依存を減らすとは、コードの合理性を損なう "不要" な依存を認識し、取り除くこと
  • オブジェクトは他オブジェクトについて知らない (オブジェクトの知識ではなくメッセージを信頼する) 方が賢くなる
  • 依存関係の方向性に関する決断はアプリケーションの寿命として現れる
  • 依存方向は自身より変更されないものに依存する

第4章 柔軟なインターフェースをつくる

パブリックインターフェースについて書かれている章。

ここでのパブリックインターフェースは、他のオブジェクトから使われることを意図して実装したメソッドのこと。

※ ここでのパブリックインターフェースは単なるパブリックメソッドではなく、静的型付け言語の Interface で定義されるようなメソッドを指していると思う。Ruby に Interface はないので、メッセージが定義されているであろうという信頼が Interface だと思った。つまりメッセージを渡す側が信頼しているメソッドが、ここでいうパブリックインターフェースだと思っている。

雑なメモは下記。

  • オブジェクト指向アプリケーションは、"クラスから成り立つ" が "メッセージによって定義される"
  • クラスは単一責任を果たすために存在するが、メソッド自体はいくつも実装する
  • パブリックインターフェースはクラスの責任を明確に述べる "契約書"
  • オブジェクトが存在するからメッセージを送るのではなく、メッセージを送るためにオブジェクトが存在する
    • "このクラスが必要なのは知っているけれど、これは何をすべきなんだろう" から "このメッセージを送る必要があるけれど、だれが応答すべきなんだろう" の思考に変える

第5章 ダックタイピングでコストを削減する

ダックタイピングやポリモーフィズムについて書かれている章。

動的型付けを恐れるな!というような表現が印象に残った。

用語

  • ダックタイピングは、特定のクラスとも結びつかないパブリックインターフェースのこと。
  • ポリモーフィズムは、多岐にわたるオブジェクトが同じメッセージに応答できる能力をさす。

雑なメモは下記。

  • Ruby におけるオブジェクトの振る舞いについての一連の想定は、パブリックインターフェースへの信頼で行われる
  • ダックタイプのパブリックインターフェースは、クラスをまたぐ型
  • ポリモーフィックなメソッドは "送り手の視点から見て" 入れ替え可能であることに合意する
  • ダックタイピング (抽象) に依存することで、メンテナンスコストが下がる

第6章 継承によって振る舞いを獲得する

継承の考え方やテクニックについて書かれた章。

雑なメモは下記。

  • 継承が常に成立するのに必要な2つのこと
    • モデル化しているオブジェクトが「汎化-特化の関係」の関係をもつ
    • 正しいコーディングスタイルを使っている
      • NotImplementedError を使ったテンプレートメソッドパターン
      • フックメッセージ

第7章 モジュールでロールの振る舞いを共有する

ロール (役割) の考え方を共有する方法について書かれた章。

雑なメモは下記。

  • どんなオブジェクトにも mixin できる Ruby のモジュールは、様々なクラスのオブジェクトが 1 カ所に定義されたコードを使って共通のロールを担うための完璧な方法

第8章 コンポジションでオブジェクトを組み合わせる

コンポジションや集約、委譲について書かれている章。

継承やロールとの比較がすごくためになる。

用語

  • コンポジションとは、組み合された全体が単なる部品の集合以上となるように、個別の部品を複雑な全体へ組み合わせる行為
  • 集約とは、コンポジションのようなものだが、包含される側のオブジェクトの存在が独立していることが異なる
    • コンポーズされたオブジェクトが消えても、包含されるオブジェクトは削除されない
  • デリゲーション (委譲) とは、単にメッセージを受け取り、どこかに転送すること

雑なメモは下記。

  • コンポジションにおいて、より大きいオブジェクトとその部品が「has-a」の関係で繋がる
  • コンポジションと集約の違いが、少しばかり実用的な影響をコードに及ぼす
  • 継承の方が良い解決法であるとはっきり言えないなら、コンポジションを使うべき
    • コンポジションの持つ依存は、継承が持つ依存よりもはるかに少ないため良い選択肢になりやすい
  • コンポジション、継承、振る舞いの共有はテクニックなので、適切に使うには経験と判断が必要。経験を得る方法は、自身の失敗から学ぶこと。試して失敗を受け入れ、容赦無くリファクタすること。

第9章 費用対効果の高いテストを設計する

テストの考え方、視点や各種手法について書かれた章。

用語

  • TDD とは、内から外へのアプローチしていくテストで、通常、ドメインオブジェクトのテストからはじまり、それらの新しくつくられたドメインオブジェクトをコードの隣接するレイヤーのテストで再利用していく。
  • BDD とは、外から内へのアプローチしていくテストで、アプリの境界でオブジェクトをつくり、内に入ってくる。まだ、かれていないオブジェクトを用意するために、モックが必要となる。

雑なメモはなし。ほとんど有益な情報ばかりでメモが多くなりすぎたので割愛します。

この本を読み終えて、オブジェクト指向について説明するなら...

オブジェクト指向とは?

世界をオブジェクト間のメッセージの受け渡しの連続として捉える考え方。

オブジェクト指向で正しく設計されたアプリケーションは、各種原則やパターンを守っているため、メンテナンス性が高く、将来予想される変更にも強い。またテストコードとの相性も良い。

オブジェクト指向のテクニックとして、継承やロールの共有、コンポジションなどがあり、正しく使うことで良い結果に導くが、誤った使い方をするとコストがかかる。正しく使うには経験と知識が必要で、それらを身につけるには失敗して受け入れ、容赦なくリファクタすることが必要。

オブジェクト指向の三大要素と言われる、クラスの継承、ポリモーフィズムカプセル化についてまとめると...

※ POODR 本を読んでからは、意識すべきはオブジェクト指向の三大要素ではなく、メッセージの送受信における正しい考え方や実装方法であって、三大要素はそれについてくるおまけ程度に感じています。

クラスの継承とは?

自動移譲の仕組みを使って、コードを短く書くテクニックのひとつで、クラス同士の関係が has-a の時に使う。構成する際は、抽象的な振る舞いをスーパクラスに、具象な振る舞いをサブクラスに置くように構成する

ポリモーフィズム(多様性)とは?

コードを短く書くテクニックのひとつで、応答オブジェクトが応答できる能力を指し、"送り手の視点から見て入れ替え可能" であること。

カプセル化とは?

具体化される知識を隠蔽させるテクニック。※ この本ではあまり触れていない

今後読みたい本について

いつ読み始めるかはわかりませんが、下記の本に興味があります。

まとめ

読んでよかった。

以上です。