これです。
自分はJava使い*1なのですが、オブジェクト指向の価値を全然活かせていないなぁと常々思っていました。
色々原因がありそうですが、この記事にあるようにしっかり考えてないからだ、ということがわかりました。
幾つか、自分に刺さったところを自分のために引用しておきます。
気になった人はリンク先の本文をぜひ読んでください。
クラスはとっかえひっかえするものをクラスにする
オブジェクト指向で書く理由、それは変更に対して柔軟に対応するためです。
(省略)
オブジェクト指向によるアプリケーション開発は、変更されない箇所を軸に、頻繁に変更される箇所をクラスに抽出するプログラミングスタイルです。
継承は様々な具体的なクラスを抽象化するためのボトムアッププロセスで、トップダウンにすべきではない
継承は機能を受け継ぐためのものではありません。継承の本質は、犬や猫を「動物」という抽象概念としてまとめ上げられるインターフェイスなのです。
その証拠として、別のクラスの機能を利用する方法にコンポジションがあります。コンポジションを使えば人間がパーツを組み合わせて「車」を作るような自然なオブジェクトの作り方ができるし、実は継承よりコンポジションの方がよく使います。
ポリモーフィズムは抽象のスーパークラスを扱う(ことによって見通しを良くする)
継承の本質はインターフェイスであると説明しましたが、ポリモーフィズムはそのインターフェイス(抽象)に対してプログラムするということです。
インスタンスをnewするのはメインクラス。メインクラスは素材を出して処理する調理場。
そのため、ファクトリを作るまでもないインスタンス生成はメインクラスで行うようにしましょう。メインクラスでnewしたインスタンスを他のクラスに渡すのです!
(省略)
メインクラスは調理場のような存在であり、メインクラスに疎結合性やモジュール性は必要ありません。そのため、メインクラスがnewの接着剤でベトベトに汚れてしまっても何も困ることはないのです。
カプセル化は難しい
しかし、小刻みにブレーキを踏まなければスリップし、小まめにギアチェンジする必要があり、カーブするときは倒れないように体重移動をしなければ倒れてしまう自動車があったら、僕はそれを運転できません。複雑だからです。だけど、ブレーキにはABSを搭載し、ギアはオートマチックで、カーブするときは倒れないよう重心が設計されていれば、あれこれ考えず運転できます。
つまりカプセル化とは複雑な部分を隠し、無駄な操作をしなくても良い状態にそのものを洗練させ、分かりやすい状態にするということです。
(省略)
実はこの「無駄を省き洗練させてわかりやすくする」というのはオブジェクト指向の原則というより、より抽象度の高い「デザイン」の原則なのです。
オブジェクト指向に不可欠なのはカプセル化ですから、つまり、オブジェクト指向でプログラミングする人にはデザインのセンスが必要になるということになります。
そんなもの、難しくて当然です!
カプセルにはただしい名前が必要
自動車には「自動車」という名前が、エレベーターには「エレベーター」という名前が付けられています。もしあなたが何かをカプセル化した場合、そのものにまだ名前が付いていない時は、それに正しい名前をつけるということが、カプセル化の最後の仕上げになります