『オブジェクト指向設計実践ガイド Rubyでわかる進化し続ける柔軟なアプリケーションの育て方』(第5章まで)要約
前置き
今回のscopeは第1章から第5章までとします。
第6章以降で扱う、継承・モジュール・コンポジション・テストは、別にまとめる方が、一つの記事としてまとまりがあると考えるためです。
気になった方は、他の記事や、原著を購入して読まれてください
ここは間違ってるんじゃない?こう理解した方がいいんじゃない?ということがありましたらご指摘お願いします
要約
第1章
オブジェクト指向とはメッセージの伝達に着目する考え。
オブジェクト指向設計とは、オブジェクト同士の依存関係を管理し、疎結合にする設計。
第2章
クラスもメソッドも単一責任にする
第3章
依存を認識する。基本的には、抽象化され、安定した、自分より変更されないものに依存する
第4章
publicメソッド: クラスの主要な責務を明らかにする
privateメソッド: 変化しやすく他のクラスのオブジェクトが依存するのが危ない
第5章
ダックタイピングとは、振る舞いによって、オブジェクトの型を定義するテクニック。
本題
第1章
オブジェクト指向設計の理解の前提として、
オブジェクト、オブジェクト指向の用語の理解と、設計は何故するのかを理解してからの方が
話は理解しやすいと考えました。なのでそこに軸足をおいてこの章を説明します。
- オブジェクトとは?
- データとメソッドにより定義される振る舞い(処理・手続き)をもつ
- オブジェクト指向とは?
- オブジェクト間のメッセージの伝達に着目する視点のことをいう。
- 補足
- 以前Kyoto.rbで、オブジェクト指向とは何か?という題材で、教えてもらった見方がわかりやすかったので載せときます。
-
世間一般でオブジェクト指向っていう言葉がでた時の2つの視点
- 構成単位に着目する見方(今では割と当たり前な見方)
- レシーバパッシブな、メッセージに着目する見方 <-本書はここ
- 設計がなぜ必要か?
- 必ず行われる変更(新機能の追加etc)の際に、変更のコストを削減するために、設計は大事。
- 現実世界の問題に当てはめると、アプリケーションが成功(ヒット)した時、設計が貧弱だと、単純であるべき変更がアプリケーション内部を伝達し、コードを破壊するから
-
オブジェクト指向設計とは?
- オブジェクト同士の依存関係を管理し、互いを知りすぎない、疎結合にする設計
- その結果、オブジェクトが変更を許容できるような形で依存関係を構成するための、コーディングテクニック
まとめると、
オブジェクトとは、データと振る舞いをもつもの
オブジェクト指向は、メッセージの伝達に着目する
設計は、変更をよりやりやすくするために必要
オブジェクト指向設計とは、オブジェクト同士の依存関係を管理し、疎結合にする設計のこと
第2章
オブジェクト指向はメッセージに着目するとはいえ、目立ってわかりやすいのはクラスです。
そのため、本書ではクラスの設計から説明を始めています。
- クラスとは?
- 似たようなオブジェクトに関する構造の設計図のこと
- 振る舞いを定義したメソッドと、変数を定義した属性をもつ
-
単一責任のクラスをつくる
- 単一責任のクラスから構成されるアプリケーションは変更が簡単。
- 反対に多くの責務をもつクラスの場合、内部がからまり、必要な振る舞いだけを取り出すことができない。
- そう入ったクラスに依存すると、そのクラスに依存する全てのクラスを破壊する可能性がある。
- だから単一責任のクラスで、着脱可能なユニットであることを維持する。
- クラスが単一責任かを見分けるための2つの方法
- クラスがもつメソッドを質問に言い換えた時、意味をなす質問になっているかどうか
- Gearクラスさん、あなたの比を教えてくれませんか OK
- Gearクラスさん、あなたのタイヤは何ですか ...???? NG
※ gear: 歯車。特に自転車の歯車式の変速装置
- 一文で、クラスを説明する
- それと / またはが入ると、そのクラスは2つ以上の責任を負っています
- (余談ですが、個人的にこれはすごくわかりやすくて、クラスを書く際に、コメントで、クラスの責務を一文で書くのを習慣にしてます!)
- クラスがもつメソッドを質問に言い換えた時、意味をなす質問になっているかどうか
- クラスがすることが全て、そのクラスの中心的な目的に関連していれば、そのクラスは 凝集度が高い* = 単一責任である!
- あらゆる箇所を単一責任にする
-
メソッドも単一責任
- 役割が何であるかを質問し、1分で責任を説明できるようにする
- メソッドを単一責任にして、見えてきた物のうち、責任がありすぎて混沌としているクラスがあれば、それらの責任は別のクラスに分ける
-
メソッドも単一責任
まとめると、
あとからの変更を簡単にするためにも、単一責任のクラスを作る
クラスが単一かを見極めるには、「メソッドを質問に言い換える」「一文でクラスを説明する」
メソッドも単一責任にし、混沌とするクラスがあればその責務を新しいクラスに切り分ける
第3章
この章では、「依存関係を管理する」手法について説明されます。
ここでいう「依存関係の管理」とは、単一責任をもつオブジェクトが、振る舞いが実装された他のオブジェクトと、共同作業をする適切な方法のことを指します。
-
「依存関係がある」とは、次のことをオブジェクトが知ってるとき
- ほかのクラスの名前
- self以外に送るメッセージの名前
- メッセージが要求する引数
- それら引数の順番 -> ハッシュ の利用
-
一般的に避けた方がいい「依存」の問題
- メッセージチェーン
- 出発と目的地の間の、途中のオブジェクトに依存関係を作り出す
- コードに対する依存関係
- メッセージチェーン
-
依存を減らすために
-
- 依存オブジェクトの注入
-
依存を隔離
-
引数の順番への依存を取り除く
- 初期化の際に引数にハッシュ を使う
- デフォルト値を指定(
||
orfetch
)
-
抽象化された、安定した性質をもつものへ依存することで、変更への直面を低減させる
- 「自分より変更されないものに依存する」
まとめると、
依存関係を認識する、それぞれに依存を減らす対策をする
基本的には、抽象化され、安定した、自分より変更されないものに依存する
第4章
この章からクラスからメッセージへと話の重点が移ります。
メッセージとは、メソッドで呼び出し(call)して、オブジェクトへ伝達するもののことです。
またインターフェースとは、クラスの主要な責務を明らかにする、public(公開情報)メソッドのことです。
- オブジェクト指向アプリケーションは、クラスから成り立つが、メッセージにより定義される
- ここでいうインターフェースとは、**クラス内にある、外部に晒されているメソッド(パブリックメソッド)**のこと
- クラス内部で、
public
(公開情報)であるメソッドと、private
(非公開情報)であるメソッドとを分ける-
publicメソッド
- 安全に依存でき、クラスの主要な責任を明らかにする -
privateメソッド
- 変化しうる部分で、他のクラスのオブジェクトが依存するのは危険。テストで言及されないことも。- (余談ですが、第9章で、privateメソッドをテストしない理由を、不安定で、他のオブジェクトによる利用を避けるためと説明があり、ハッとしました!!!!)
-
-
メッセージに基づく設計へ視点を変更し、このメッセージを送る必要があるけど、誰が応答すべきかと思考を変える
- シーケンス図を書くことにより、パブリックインターフェースとして公開すべきメソッドを顕にし、メッセージを明らかにすることができる
- publicインターフェースでは、「何を」に着目し、依頼先のクラスの責務として「どのように」(方法)を任せる
- **「私は自分が何を望んでいるか知っているし、あなたがあなたの担当部分をやってくれると信じているよ」**が理想
まとめると、
オブジェクト指向アプリケーションはメッセージにより定義される
クラス内部で、クラスの主要な責務を明らかにするpublicメソッドと変化しやすく他のクラスのオブジェクトが依存するのが危ないprivateメソッドを分ける
「どのように」については、依頼先クラスを信頼し、そのクラスの責務として任せる
第5章
はじめに
ダックタイピングの背景には、
メッセージを設計の中心におく、パブリックインターフェースを構築するという2つの考えがあります
- ダックタイピングとは
- オブジェクトを、クラスではなく、メッセージ(振る舞い)によって定義するテクニック
- オブジェクトを特定のクラスから切り離し、
何を「する」
かで、オブジェクトの仮想の型
を定義する
- ポリモーフィズムとは
- 相手がどのクラスのオブジェクトかを意識せずに、メッセージを送れる仕組み
- 同じ名前のメソッドを複数のクラスで使用できるようにし、そのメソッドを通して、暗黙的に複数のインスタンスの動作を切り替えれるようにすること
- ダックタイピングを認識する3つの
- クラスで分岐するcase文
- kind_of?とis_a?
- responds_to?
- ダックタイピングという言葉に囚われすぎずに、これらが出てきた時に、ダックタイピングができないかどうか考えてみるくらいの温度感からまず、接してみるといいのかも。
まとめると、
ダックタイピングとは、振る舞いによって、オブジェクトの型を定義するテクニック。
ダックタイプを見極める3条件を見つけると、まず疑ってみる。
読後感想
オブジェクト指向設計の考えが深まった。
ただ、第5章のダックタイピングの章が、何を目的として、独立した章を用意しているのかが僕の理解では追いつきませんでした
Rubyでは、型≠クラスで、振る舞いによって型が規定される
ことを示すため??
時間を置いて、読み返してみよう。