ravelll の日記

よしなに

オブジェクト指向設計実践ガイド 第5章

5章はダックタイピングの話。Ruby の特徴としてよく語られますね。

勘所がつかめると設計が洗練されるだけでなく OSS プロダクトのコードリーディングが捗って良さそうだな〜と思いました。

動的/静的型付け言語の話はなかなか強い口調で語られていて、読んでいて少しヒヤヒヤするところがあった。

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

  • ダックタイプ:どの特定のクラスにも結びつかない(クラスをまたぐ)パブリックインターフェース
  • 「アヒルのように鳴き、アヒルのように歩くならば、それはアヒルである」

5.1 ダックタイピングを理解する

  • Ruby ではパブリックインターフェースを信頼を元にオブジェクトの振る舞いを期待する
    • 「あるオブジェクトの型を知っている」ことは「オブジェクトが応答できるメッセージを知っている」ということ
    • あるクラス A のオブジェクトと相互作用するオブジェクトに必要なことは「相手が A のインターフェースを実装していると信頼する」こと
  • オブジェクトの使い手はそのクラスを気にする必要がなく、気にするべきでない
    • 重要なことはオブジェクトが「何であるか」でなく「何をするか」
  • ダックタイプのパブリックインターフェースは契約を表す
  • Trip#prepare は Mechanic クラスには依存していないが「prepare_bicycles に応答できるオブジェクトを受け取る」ことに依存している
  • ダックタイプ化は少しの理解力と引き換えに拡張の容易さを提供する
    • 具象的なコードは理解易・拡張難、抽象的なコードは理解難・拡張易
  • オブジェクト指向におけるポリモーフィズム:種々のオブジェクトが同じメッセージに応答できる能力

5.2 ダックを信頼するコードを書く

  • クラスによって分岐する case 文は未特定のダックの存在を示唆する
    • 共同作業するオブジェクトについての知識を持ちすぎていて、信頼が欠けている
  • ダックタイプを実装するクラスは振る舞いもいくらか共有する必要がある
    • モジュールによってロールを共有する方法に続く
  • ダックタイプは時と場合を考えて使う
    • ダックタイプを見つけて実装してもアプリケーション全体のコストが下がらない場合もある

5.3 ダックタイピングへの恐れを克服する

  • コンパイラは不慮の型エラーからプログラマーを救うことはできない
    • 変数を新しい型にキャストできる全ての言語には脆さがある
  • 静的型付けによって安全になるという考えは幻想である
  • 現実の世界で、コンパイラで防げる実行時の型エラーはほぼ確実に起こらない
    • コンパイラの助けがなければ型エラーは起こる、という説に対して
  • 動的型付け言語は、高コスト低価値なコンパイル時の型検査と、コンパイル/make サイクルを除くことで得られる莫大な効率性とを交換してくれる
    • :fire:

5.4 まとめ

  • ダックタイピングはパブリックインターフェースを特定のクラスから切り離し、「何であるか」ではなく「何をするか」によって定義される仮想の型を作る